From e697eb3ae38bbda0b1b4803ea03a73067881dec2 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 10 May 2024 23:58:27 +0200 Subject: [PATCH 001/233] Feat: Make connection data exposed in api less prone to throw errors (#4604) * Feat: Make connection data exposed in api less prone to throw errors * address reviews * review --- .../connection/ConnectionRequestEvent.java | 26 +++++++++++++++++-- .../network/GeyserServerInitializer.java | 5 ---- .../geyser/network/UpstreamPacketHandler.java | 4 +++ .../geyser/session/GeyserSession.java | 12 +++++---- 4 files changed, 35 insertions(+), 12 deletions(-) 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 index 5c1f4ef51..b36ee8bfb 100644 --- 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 @@ -46,13 +46,35 @@ public final class ConnectionRequestEvent implements Event, Cancellable { this.proxyIp = proxyIp; } + /** + * The IP address of the client attempting to connect + * + * @return the IP address of the client attempting to connect + * @deprecated Use {@link #inetSocketAddress()} instead + */ + @NonNull @Deprecated(forRemoval = true) + 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 + * @deprecated Use {@link #proxyIp()} instead + */ + @Nullable @Deprecated(forRemoval = true) + public InetSocketAddress getProxyIp() { + return proxyIp; + } + /** * The IP address of the client attempting to connect * * @return the IP address of the client attempting to connect */ @NonNull - public InetSocketAddress getInetSocketAddress() { + public InetSocketAddress inetSocketAddress() { return ip; } @@ -62,7 +84,7 @@ public final class ConnectionRequestEvent implements Event, Cancellable { * @return the IP address of the proxy handling the connection */ @Nullable - public InetSocketAddress getProxyIp() { + public InetSocketAddress proxyIp() { return proxyIp; } 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 662e2f4c7..5c83702ae 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GeyserServerInitializer.java +++ b/core/src/main/java/org/geysermc/geyser/network/GeyserServerInitializer.java @@ -25,11 +25,8 @@ 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; @@ -37,7 +34,6 @@ 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; import org.geysermc.geyser.session.GeyserSession; import java.net.InetSocketAddress; @@ -72,7 +68,6 @@ public class GeyserServerInitializer extends BedrockServerInitializer { 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) { // Error must be caught or it will be swallowed this.geyser.getLogger().error("Error occurred while initializing player!", e); 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 59485b2cd..23ab1697f 100644 --- a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java @@ -54,6 +54,7 @@ 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.event.bedrock.SessionInitializeEvent; import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.api.pack.PackCodec; import org.geysermc.geyser.api.pack.ResourcePack; @@ -188,6 +189,9 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { return PacketSignal.HANDLED; } + // Fire SessionInitializeEvent here as we now know the client data + geyser.eventBus().fire(new SessionInitializeEvent(session)); + PlayStatusPacket playStatus = new PlayStatusPacket(); playStatus.setStatus(PlayStatusPacket.Status.LOGIN_SUCCESS); session.sendUpstreamPacket(playStatus); 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..617087f71 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -1077,9 +1077,11 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { if (!closed) { loggedIn = false; - // Fire SessionDisconnectEvent SessionDisconnectEvent disconnectEvent = new SessionDisconnectEvent(this, reason); - geyser.getEventBus().fire(disconnectEvent); + if (authData != null && clientData != null) { // can occur if player disconnects before Bedrock auth finishes + // Fire SessionDisconnectEvent + geyser.getEventBus().fire(disconnectEvent); + } // Disconnect downstream if necessary if (downstream != null) { @@ -1404,7 +1406,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Override public String name() { - return null; + return playerEntity != null ? javaUsername() : bedrockUsername(); } @Override @@ -1941,12 +1943,12 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Override public @MonotonicNonNull String javaUsername() { - return playerEntity.getUsername(); + return playerEntity != null ? playerEntity.getUsername() : null; } @Override public UUID javaUuid() { - return playerEntity.getUuid(); + return playerEntity != null ? playerEntity.getUuid() : null ; } @Override From 7801e357fb3c8e8ffecd9fb01c143d1c8343106c Mon Sep 17 00:00:00 2001 From: Teelair Date: Fri, 10 May 2024 17:20:52 -0600 Subject: [PATCH 002/233] Map new Mace enchantments for Bedrock clients (#4653) * Map new Mace enchantments for Bedrock clients * Move to using a map for Java-only enchantments. * Change to using null check for translationKey --- .../org/geysermc/geyser/item/type/Item.java | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) 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 bfcfb23d1..fc4fda07c 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 @@ -53,6 +53,16 @@ import java.util.List; import java.util.Map; public class Item { + /** + * This is a map from Java-only enchantments to their translation keys so that we can + * map these enchantments to Bedrock clients, since they don't actually exist there. + */ + private static final Map ENCHANTMENT_TRANSLATION_KEYS = Map.of( + Enchantment.JavaEnchantment.SWEEPING_EDGE, "enchantment.minecraft.sweeping", + Enchantment.JavaEnchantment.DENSITY, "enchantment.minecraft.density", + Enchantment.JavaEnchantment.BREACH, "enchantment.minecraft.breach", + Enchantment.JavaEnchantment.WIND_BURST, "enchantment.minecraft.wind_burst"); + private final String javaIdentifier; private int javaId = -1; private final int stackSize; @@ -227,8 +237,10 @@ public class Item { // TODO verify // TODO streamline Enchantment process Enchantment.JavaEnchantment enchantment = Enchantment.JavaEnchantment.of(enchantId); - if (enchantment == Enchantment.JavaEnchantment.SWEEPING_EDGE) { - addSweeping(session, builder, level); + String translationKey = ENCHANTMENT_TRANSLATION_KEYS.get(enchantment); + if (translationKey != null) { + String enchantmentTranslation = MinecraftLocale.getLocaleString(translationKey, session.locale()); + addJavaOnlyEnchantment(session, builder, enchantmentTranslation, level); return null; } if (enchantment == null) { @@ -242,11 +254,10 @@ public class Item { .build(); } - private void addSweeping(GeyserSession session, BedrockItemBuilder builder, int level) { - String sweepingTranslation = MinecraftLocale.getLocaleString("enchantment.minecraft.sweeping", session.locale()); + private void addJavaOnlyEnchantment(GeyserSession session, BedrockItemBuilder builder, String enchantmentName, int level) { String lvlTranslation = MinecraftLocale.getLocaleString("enchantment.level." + level, session.locale()); - builder.getOrCreateLore().add(ChatColor.RESET + ChatColor.GRAY + sweepingTranslation + " " + lvlTranslation); + builder.getOrCreateLore().add(ChatColor.RESET + ChatColor.GRAY + enchantmentName + " " + lvlTranslation); } /* Translation methods end */ From 86dafbc108fbc86a5d100b84804321a30f438883 Mon Sep 17 00:00:00 2001 From: chris Date: Sun, 12 May 2024 10:49:08 +0200 Subject: [PATCH 003/233] Ensure we load mod resources correctly on Geyser-NeoForge (#4651) * correctly load jar resource files on neoforge * also add support for neoforge-floodgate --- bootstrap/mod/neoforge/build.gradle.kts | 4 ++- .../neoforge/GeyserNeoForgeBootstrap.java | 5 ++-- .../neoforge/GeyserNeoForgePlatform.java | 25 ++++++++++++++++--- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/bootstrap/mod/neoforge/build.gradle.kts b/bootstrap/mod/neoforge/build.gradle.kts index ff77bcc5c..92ffae7e5 100644 --- a/bootstrap/mod/neoforge/build.gradle.kts +++ b/bootstrap/mod/neoforge/build.gradle.kts @@ -31,7 +31,9 @@ dependencies { // Let's shade in our own api shadow(projects.api) { isTransitive = false } - shadow(projects.common) { isTransitive = false } + + // cannot be shaded, since neoforge will complain if floodgate-neoforge tries to provide this + include(projects.common) // Include all transitive deps of core via JiJ includeTransitive(projects.core) 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 1655dea91..b97e42389 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,6 +27,7 @@ package org.geysermc.geyser.platform.neoforge; import net.minecraft.commands.CommandSourceStack; import net.minecraft.world.entity.player.Player; +import net.neoforged.fml.ModContainer; import net.neoforged.fml.common.Mod; import net.neoforged.fml.loading.FMLLoader; import net.neoforged.neoforge.common.NeoForge; @@ -43,8 +44,8 @@ public class GeyserNeoForgeBootstrap extends GeyserModBootstrap { private final GeyserNeoForgePermissionHandler permissionHandler = new GeyserNeoForgePermissionHandler(); - public GeyserNeoForgeBootstrap() { - super(new GeyserNeoForgePlatform()); + public GeyserNeoForgeBootstrap(ModContainer container) { + super(new GeyserNeoForgePlatform(container)); if (isServer()) { // Set as an event so we can get the proper IP and port if needed 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 index 63abe4a4a..41562baf3 100644 --- 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 @@ -26,20 +26,29 @@ package org.geysermc.geyser.platform.neoforge; import net.minecraft.server.MinecraftServer; +import net.neoforged.fml.ModContainer; +import net.neoforged.fml.ModList; 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.IOException; import java.io.InputStream; +import java.nio.file.Files; import java.nio.file.Path; public class GeyserNeoForgePlatform implements GeyserModPlatform { + private final ModContainer container; + + public GeyserNeoForgePlatform(ModContainer container) { + this.container = container; + } + @Override public @NonNull PlatformType platformType() { return PlatformType.NEOFORGE; @@ -62,11 +71,21 @@ public class GeyserNeoForgePlatform implements GeyserModPlatform { @Override public boolean testFloodgatePluginPresent(@NonNull GeyserModBootstrap bootstrap) { - return false; // No Floodgate mod for NeoForge yet + if (ModList.get().isLoaded("floodgate")) { + Path floodgateDataFolder = FMLPaths.CONFIGDIR.get().resolve("floodgate"); + bootstrap.getGeyserConfig().loadFloodgate(bootstrap, floodgateDataFolder); + return true; + } + return false; } @Override public @Nullable InputStream resolveResource(@NonNull String resource) { - return GeyserBootstrap.class.getClassLoader().getResourceAsStream(resource); + try { + Path path = container.getModInfo().getOwningFile().getFile().findResource(resource); + return Files.newInputStream(path); + } catch (IOException e) { + return null; + } } } From b11a6d7176bb046dbc0b91a8d2faf251342978e5 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Tue, 14 May 2024 13:22:54 +0100 Subject: [PATCH 004/233] Remove unofficial skin sources and add skin event for extensions (#4507) * Remove ears and unoffical skin sources * Remove supplyEars * Cleanup and add SkinApplyEvent * Add failed back to skin * Accept suggestion on SkinGeometry Co-authored-by: chris * Add javadoc and update copyright * Remove old config options * Make SkinApplyEvent a ConnectionEvent * Add warning about third-party config options * Update warning message * Add javadoc to event * Fix javadoc * Ajust for review and bump version to 2.2.4 * Get rid of array and preserve original skin data * Add originalSkin method to event * Handle NonNull in SessionSkinApplyEvent * Revert default copyright change --------- Co-authored-by: chris --- .idea/copyright/Geyser.xml | 3 +- .../event/bedrock/SessionSkinApplyEvent.java | 144 +++++++ .../org/geysermc/geyser/api/skin/Cape.java | 40 ++ .../org/geysermc/geyser/api/skin/Skin.java | 39 ++ .../geysermc/geyser/api/skin/SkinData.java | 32 ++ .../geyser/api/skin/SkinGeometry.java | 48 +++ .../configuration/GeyserConfiguration.java | 4 +- .../geyser/pack/SkullResourcePackManager.java | 4 +- .../geyser/skin/FakeHeadProvider.java | 36 +- .../geysermc/geyser/skin/ProvidedSkins.java | 9 +- .../org/geysermc/geyser/skin/SkinManager.java | 42 +- .../geysermc/geyser/skin/SkinProvider.java | 406 ++++-------------- .../geyser/skin/SkullSkinManager.java | 14 +- .../bedrock/skin/geometry.humanoid.ears.json | 249 ----------- .../skin/geometry.humanoid.earsSlim.json | 249 ----------- core/src/main/resources/config.yml | 8 - gradle.properties | 2 +- 17 files changed, 444 insertions(+), 885 deletions(-) create mode 100644 api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionSkinApplyEvent.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/skin/Cape.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/skin/Skin.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/skin/SkinData.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/skin/SkinGeometry.java delete mode 100644 core/src/main/resources/bedrock/skin/geometry.humanoid.ears.json delete mode 100644 core/src/main/resources/bedrock/skin/geometry.humanoid.earsSlim.json diff --git a/.idea/copyright/Geyser.xml b/.idea/copyright/Geyser.xml index c6b553aaf..758c31cbd 100644 --- a/.idea/copyright/Geyser.xml +++ b/.idea/copyright/Geyser.xml @@ -1,6 +1,7 @@ - \ No newline at end of file diff --git a/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionSkinApplyEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionSkinApplyEvent.java new file mode 100644 index 000000000..f22241e41 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/event/bedrock/SessionSkinApplyEvent.java @@ -0,0 +1,144 @@ +/* + * 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.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.skin.Cape; +import org.geysermc.geyser.api.skin.Skin; +import org.geysermc.geyser.api.skin.SkinData; +import org.geysermc.geyser.api.skin.SkinGeometry; + +import java.util.UUID; + +/** + * Called when a skin is applied to a player. + *

+ * Won't be called when a fake player is spawned for a player skull. + */ +public abstract class SessionSkinApplyEvent extends ConnectionEvent { + + private final String username; + private final UUID uuid; + private final boolean slim; + private final boolean bedrock; + private final SkinData originalSkinData; + + public SessionSkinApplyEvent(@NonNull GeyserConnection connection, String username, UUID uuid, boolean slim, boolean bedrock, SkinData skinData) { + super(connection); + this.username = username; + this.uuid = uuid; + this.slim = slim; + this.bedrock = bedrock; + this.originalSkinData = skinData; + } + + /** + * The username of the player. + * + * @return the username of the player + */ + public @NonNull String username() { + return username; + } + + /** + * The UUID of the player. + * + * @return the UUID of the player + */ + public @NonNull UUID uuid() { + return uuid; + } + + /** + * If the player is using a slim model. + * + * @return if the player is using a slim model + */ + public boolean slim() { + return slim; + } + + /** + * If the player is a Bedrock player. + * + * @return if the player is a Bedrock player + */ + public boolean bedrock() { + return bedrock; + } + + /** + * The original skin data of the player. + * + * @return the original skin data of the player + */ + public @NonNull SkinData originalSkin() { + return originalSkinData; + } + + /** + * The skin data of the player. + * + * @return the current skin data of the player + */ + public abstract @NonNull SkinData skinData(); + + /** + * Change the skin of the player. + * + * @param newSkin the new skin + */ + public abstract void skin(@NonNull Skin newSkin); + + /** + * Change the cape of the player. + * + * @param newCape the new cape + */ + public abstract void cape(@NonNull Cape newCape); + + /** + * Change the geometry of the player. + * + * @param newGeometry the new geometry + */ + public abstract void geometry(@NonNull SkinGeometry newGeometry); + + /** + * Change the geometry of the player. + *

+ * Constructs a generic {@link SkinGeometry} object with the given data. + * + * @param geometryName the name of the geometry + * @param geometryData the data of the geometry + */ + public void geometry(@NonNull String geometryName, @NonNull String geometryData) { + geometry(new SkinGeometry("{\"geometry\" :{\"default\" :\"" + geometryName + "\"}}", geometryData)); + } +} diff --git a/api/src/main/java/org/geysermc/geyser/api/skin/Cape.java b/api/src/main/java/org/geysermc/geyser/api/skin/Cape.java new file mode 100644 index 000000000..1e7341ae4 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/skin/Cape.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 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.skin; + +/** + * Represents a cape. + * + * @param textureUrl The URL of the cape texture + * @param capeId The ID of the cape + * @param capeData The raw cape image data in ARGB format + * @param failed If the cape failed to load, this is for things like fallback capes + */ +public record Cape(String textureUrl, String capeId, byte[] capeData, boolean failed) { + public Cape(String textureUrl, String capeId, byte[] capeData) { + this(textureUrl, capeId, capeData, false); + } +} diff --git a/api/src/main/java/org/geysermc/geyser/api/skin/Skin.java b/api/src/main/java/org/geysermc/geyser/api/skin/Skin.java new file mode 100644 index 000000000..9b39ddfe8 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/skin/Skin.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 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.skin; + +/** + * Represents a skin. + * + * @param textureUrl The URL/ID of the skin texture + * @param skinData The raw skin image data in ARGB + * @param failed If the skin failed to load, this is for things like fallback skins + */ +public record Skin(String textureUrl, byte[] skinData, boolean failed) { + public Skin(String textureUrl, byte[] skinData) { + this(textureUrl, skinData, false); + } +} diff --git a/api/src/main/java/org/geysermc/geyser/api/skin/SkinData.java b/api/src/main/java/org/geysermc/geyser/api/skin/SkinData.java new file mode 100644 index 000000000..9de4a3534 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/skin/SkinData.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 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.skin; + +/** + * Represents a full package of {@link Skin}, {@link Cape}, and {@link SkinGeometry}. + */ +public record SkinData(Skin skin, Cape cape, SkinGeometry geometry) { +} diff --git a/api/src/main/java/org/geysermc/geyser/api/skin/SkinGeometry.java b/api/src/main/java/org/geysermc/geyser/api/skin/SkinGeometry.java new file mode 100644 index 000000000..5b40d2022 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/skin/SkinGeometry.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 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.skin; + +/** + * Represents geometry of a skin. + * + * @param geometryName The name of the geometry (JSON) + * @param geometryData The geometry data (JSON) + */ +public record SkinGeometry(String geometryName, String geometryData) { + + public static SkinGeometry WIDE = getLegacy(false); + public static SkinGeometry SLIM = getLegacy(true); + + /** + * Generate generic geometry + * + * @param isSlim if true, it will be the slimmer alex model + * @return The generic geometry object + */ + private static SkinGeometry getLegacy(boolean isSlim) { + return new SkinGeometry("{\"geometry\" :{\"default\" :\"geometry.humanoid.custom" + (isSlim ? "Slim" : "") + "\"}}", ""); + } +} 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 d12ab79e9..88bb98171 100644 --- a/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java +++ b/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.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 @@ -72,8 +72,10 @@ public interface GeyserConfiguration { boolean isDebugMode(); + @Deprecated boolean isAllowThirdPartyCapes(); + @Deprecated boolean isAllowThirdPartyEars(); String getShowCooldown(); 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 f0faa4244..59651d139 100644 --- a/core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.java +++ b/core/src/main/java/org/geysermc/geyser/pack/SkullResourcePackManager.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 @@ -118,7 +118,7 @@ public class SkullResourcePackManager { return; } - BufferedImage image = SkinProvider.requestImage(skinUrl, null); + BufferedImage image = SkinProvider.requestImage(skinUrl, false); // 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 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 d2a45b614..ef3ff3293 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/FakeHeadProvider.java +++ b/core/src/main/java/org/geysermc/geyser/skin/FakeHeadProvider.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 @@ -38,6 +38,10 @@ import lombok.Getter; import lombok.Setter; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.skin.Cape; +import org.geysermc.geyser.api.skin.Skin; +import org.geysermc.geyser.api.skin.SkinData; +import org.geysermc.geyser.api.skin.SkinGeometry; import org.geysermc.geyser.entity.type.LivingEntity; import org.geysermc.geyser.entity.type.player.PlayerEntity; import org.geysermc.geyser.session.GeyserSession; @@ -59,27 +63,27 @@ import java.util.concurrent.TimeUnit; * Responsible for modifying a player's skin when wearing a player head */ public class FakeHeadProvider { - private static final LoadingCache MERGED_SKINS_LOADING_CACHE = CacheBuilder.newBuilder() + private static final LoadingCache MERGED_SKINS_LOADING_CACHE = CacheBuilder.newBuilder() .expireAfterAccess(1, TimeUnit.HOURS) .maximumSize(10000) .build(new CacheLoader<>() { @Override - public SkinProvider.SkinData load(@NonNull FakeHeadEntry fakeHeadEntry) throws Exception { - SkinProvider.SkinData skinData = SkinProvider.getOrDefault(SkinProvider.requestSkinData(fakeHeadEntry.getEntity()), null, 5); + public SkinData load(@NonNull FakeHeadEntry fakeHeadEntry) throws Exception { + SkinData skinData = SkinProvider.getOrDefault(SkinProvider.requestSkinData(fakeHeadEntry.getEntity(), fakeHeadEntry.getSession()), null, 5); if (skinData == null) { throw new Exception("Couldn't load player's original skin"); } - SkinProvider.Skin skin = skinData.skin(); - SkinProvider.Cape cape = skinData.cape(); - SkinProvider.SkinGeometry geometry = skinData.geometry().geometryName().equals("{\"geometry\" :{\"default\" :\"geometry.humanoid.customSlim\"}}") + Skin skin = skinData.skin(); + Cape cape = skinData.cape(); + SkinGeometry geometry = skinData.geometry().geometryName().equals("{\"geometry\" :{\"default\" :\"geometry.humanoid.customSlim\"}}") ? SkinProvider.WEARING_CUSTOM_SKULL_SLIM : SkinProvider.WEARING_CUSTOM_SKULL; - SkinProvider.Skin headSkin = SkinProvider.getOrDefault( + Skin headSkin = SkinProvider.getOrDefault( SkinProvider.requestSkin(fakeHeadEntry.getEntity().getUuid(), fakeHeadEntry.getFakeHeadSkinUrl(), false), SkinProvider.EMPTY_SKIN, 5); - BufferedImage originalSkinImage = SkinProvider.imageDataToBufferedImage(skin.getSkinData(), 64, skin.getSkinData().length / 4 / 64); - BufferedImage headSkinImage = SkinProvider.imageDataToBufferedImage(headSkin.getSkinData(), 64, headSkin.getSkinData().length / 4 / 64); + BufferedImage originalSkinImage = SkinProvider.imageDataToBufferedImage(skin.skinData(), 64, skin.skinData().length / 4 / 64); + BufferedImage headSkinImage = SkinProvider.imageDataToBufferedImage(headSkin.skinData(), 64, headSkin.skinData().length / 4 / 64); Graphics2D graphics2D = originalSkinImage.createGraphics(); graphics2D.setComposite(AlphaComposite.Clear); @@ -90,14 +94,15 @@ public class FakeHeadProvider { // Make the skin key a combination of the current skin data and the new skin data // Don't tie it to a player - that player *can* change skins in-game - String skinKey = "customPlayerHead_" + fakeHeadEntry.getFakeHeadSkinUrl() + "_" + skin.getTextureUrl(); + String skinKey = "customPlayerHead_" + fakeHeadEntry.getFakeHeadSkinUrl() + "_" + skin.textureUrl(); byte[] targetSkinData = SkinProvider.bufferedImageToImageData(originalSkinImage); - SkinProvider.Skin mergedSkin = new SkinProvider.Skin(fakeHeadEntry.getEntity().getUuid(), skinKey, targetSkinData, System.currentTimeMillis(), false, false); + Skin mergedSkin = new Skin(skinKey, targetSkinData); // Avoiding memory leak fakeHeadEntry.setEntity(null); + fakeHeadEntry.setSession(null); - return new SkinProvider.SkinData(mergedSkin, cape, geometry); + return new SkinData(mergedSkin, cape, geometry); } }); @@ -164,7 +169,7 @@ public class FakeHeadProvider { String texturesProperty = entity.getTexturesProperty(); SkinProvider.getExecutorService().execute(() -> { try { - SkinProvider.SkinData mergedSkinData = MERGED_SKINS_LOADING_CACHE.get(new FakeHeadEntry(texturesProperty, fakeHeadSkinUrl, entity)); + SkinData mergedSkinData = MERGED_SKINS_LOADING_CACHE.get(new FakeHeadEntry(texturesProperty, fakeHeadSkinUrl, entity, session)); SkinManager.sendSkinPacket(session, entity, mergedSkinData); } catch (ExecutionException e) { GeyserImpl.getInstance().getLogger().error("Couldn't merge skin of " + entity.getUsername() + " with head skin url " + fakeHeadSkinUrl, e); @@ -181,7 +186,7 @@ public class FakeHeadProvider { return; } - SkinProvider.requestSkinData(entity).whenCompleteAsync((skinData, throwable) -> { + SkinProvider.requestSkinData(entity, session).whenCompleteAsync((skinData, throwable) -> { if (throwable != null) { GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.skin.fail", entity.getUuid()), throwable); return; @@ -198,6 +203,7 @@ public class FakeHeadProvider { private final String texturesProperty; private final String fakeHeadSkinUrl; private PlayerEntity entity; + private GeyserSession session; @Override public boolean equals(Object o) { 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 58c8f0072..ba74fbb42 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/ProvidedSkins.java +++ b/core/src/main/java/org/geysermc/geyser/skin/ProvidedSkins.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 @@ -26,6 +26,7 @@ package org.geysermc.geyser.skin; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.skin.Skin; import org.geysermc.geyser.util.AssetUtils; import javax.imageio.ImageIO; @@ -67,7 +68,7 @@ public final class ProvidedSkins { } public static final class ProvidedSkin { - private SkinProvider.Skin data; + private Skin data; private final boolean slim; ProvidedSkin(String asset, boolean slim) { @@ -94,14 +95,14 @@ public final class ProvidedSkins { image.flush(); String identifier = "geysermc:" + assetName + "_" + (slim ? "slim" : "wide"); - this.data = new SkinProvider.Skin(-1, identifier, byteData); + this.data = new Skin(identifier, byteData, true); } catch (IOException e) { e.printStackTrace(); } })); } - public SkinProvider.Skin getData() { + public Skin getData() { // Fall back to the default skin if we can't load our skins, or it's not loaded yet. return Objects.requireNonNullElse(data, SkinProvider.EMPTY_SKIN); } 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 4f3a94688..7b126c136 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/SkinManager.java +++ b/core/src/main/java/org/geysermc/geyser/skin/SkinManager.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 @@ -34,6 +34,10 @@ import org.cloudburstmc.protocol.bedrock.data.skin.SerializedSkin; import org.cloudburstmc.protocol.bedrock.packet.PlayerListPacket; import org.cloudburstmc.protocol.bedrock.packet.PlayerSkinPacket; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.skin.Cape; +import org.geysermc.geyser.api.skin.Skin; +import org.geysermc.geyser.api.skin.SkinData; +import org.geysermc.geyser.api.skin.SkinGeometry; import org.geysermc.geyser.entity.type.player.PlayerEntity; import org.geysermc.geyser.entity.type.player.SkullPlayerEntity; import org.geysermc.geyser.session.GeyserSession; @@ -56,21 +60,21 @@ public class SkinManager { public static PlayerListPacket.Entry buildCachedEntry(GeyserSession session, PlayerEntity playerEntity) { // First: see if we have the cached skin texture ID. GameProfileData data = GameProfileData.from(playerEntity); - SkinProvider.Skin skin = null; - SkinProvider.Cape cape = null; - SkinProvider.SkinGeometry geometry = SkinProvider.SkinGeometry.WIDE; + Skin skin = null; + Cape cape = null; + SkinGeometry geometry = SkinGeometry.WIDE; if (data != null) { // GameProfileData is not null = server provided us with textures data to work with. skin = SkinProvider.getCachedSkin(data.skinUrl()); cape = SkinProvider.getCachedCape(data.capeUrl()); - geometry = data.isAlex() ? SkinProvider.SkinGeometry.SLIM : SkinProvider.SkinGeometry.WIDE; + geometry = data.isAlex() ? SkinGeometry.SLIM : SkinGeometry.WIDE; } if (skin == null || cape == null) { // The server either didn't have a texture to send, or we didn't have the texture ID cached. // Let's see if this player is a Bedrock player, and if so, let's pull their skin. // Otherwise, grab the default player skin - SkinProvider.SkinData fallbackSkinData = SkinProvider.determineFallbackSkinData(playerEntity.getUuid()); + SkinData fallbackSkinData = SkinProvider.determineFallbackSkinData(playerEntity.getUuid()); if (skin == null) { skin = fallbackSkinData.skin(); geometry = fallbackSkinData.geometry(); @@ -95,10 +99,10 @@ public class SkinManager { * With all the information needed, build a Bedrock player entry with translated skin information. */ public static PlayerListPacket.Entry buildEntryManually(GeyserSession session, UUID uuid, String username, long geyserId, - SkinProvider.Skin skin, - SkinProvider.Cape cape, - SkinProvider.SkinGeometry geometry) { - SerializedSkin serializedSkin = getSkin(skin.getTextureUrl(), skin, cape, geometry); + Skin skin, + Cape cape, + SkinGeometry geometry) { + SerializedSkin serializedSkin = getSkin(skin.textureUrl(), skin, cape, geometry); // This attempts to find the XUID of the player so profile images show up for Xbox accounts String xuid = ""; @@ -128,10 +132,10 @@ public class SkinManager { return entry; } - public static void sendSkinPacket(GeyserSession session, PlayerEntity entity, SkinProvider.SkinData skinData) { - SkinProvider.Skin skin = skinData.skin(); - SkinProvider.Cape cape = skinData.cape(); - SkinProvider.SkinGeometry geometry = skinData.geometry(); + public static void sendSkinPacket(GeyserSession session, PlayerEntity entity, SkinData skinData) { + Skin skin = skinData.skin(); + Cape cape = skinData.cape(); + SkinGeometry geometry = skinData.geometry(); if (entity.getUuid().equals(session.getPlayerEntity().getUuid())) { // TODO is this special behavior needed? @@ -153,23 +157,23 @@ public class SkinManager { PlayerSkinPacket packet = new PlayerSkinPacket(); packet.setUuid(entity.getUuid()); packet.setOldSkinName(""); - packet.setNewSkinName(skin.getTextureUrl()); - packet.setSkin(getSkin(skin.getTextureUrl(), skin, cape, geometry)); + packet.setNewSkinName(skin.textureUrl()); + packet.setSkin(getSkin(skin.textureUrl(), skin, cape, geometry)); packet.setTrustedSkin(true); session.sendUpstreamPacket(packet); } } - private static SerializedSkin getSkin(String skinId, SkinProvider.Skin skin, SkinProvider.Cape cape, SkinProvider.SkinGeometry geometry) { + private static SerializedSkin getSkin(String skinId, Skin skin, Cape cape, SkinGeometry geometry) { return SerializedSkin.of(skinId, "", geometry.geometryName(), - ImageData.of(skin.getSkinData()), Collections.emptyList(), + ImageData.of(skin.skinData()), Collections.emptyList(), ImageData.of(cape.capeData()), geometry.geometryData(), "", true, false, false, cape.capeId(), skinId); } public static void requestAndHandleSkinAndCape(PlayerEntity entity, GeyserSession session, Consumer skinAndCapeConsumer) { - SkinProvider.requestSkinData(entity).whenCompleteAsync((skinData, throwable) -> { + SkinProvider.requestSkinData(entity, session).whenCompleteAsync((skinData, throwable) -> { if (skinData == null) { if (skinAndCapeConsumer != null) { skinAndCapeConsumer.accept(null); 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 683712c22..3b31dfff8 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java +++ b/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java @@ -35,7 +35,12 @@ 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.event.bedrock.SessionSkinApplyEvent; import org.geysermc.geyser.api.network.AuthType; +import org.geysermc.geyser.api.skin.Cape; +import org.geysermc.geyser.api.skin.Skin; +import org.geysermc.geyser.api.skin.SkinData; +import org.geysermc.geyser.api.skin.SkinGeometry; import org.geysermc.geyser.entity.type.player.PlayerEntity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; @@ -45,7 +50,6 @@ import org.geysermc.geyser.util.WebUtils; import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; @@ -57,11 +61,10 @@ import java.util.concurrent.*; import java.util.function.Predicate; public class SkinProvider { - private static final boolean ALLOW_THIRD_PARTY_CAPES = GeyserImpl.getInstance().getConfig().isAllowThirdPartyCapes(); private static ExecutorService EXECUTOR_SERVICE; static final Skin EMPTY_SKIN; - static final Cape EMPTY_CAPE = new Cape("", "no-cape", ByteArrays.EMPTY_ARRAY, -1, true); + static final Cape EMPTY_CAPE = new Cape("", "no-cape", ByteArrays.EMPTY_ARRAY, true); private static final Cache CACHED_JAVA_CAPES = CacheBuilder.newBuilder() .expireAfterAccess(1, TimeUnit.HOURS) @@ -88,9 +91,6 @@ public class SkinProvider { */ private static final Predicate IS_NPC = uuid -> uuid.version() == 2; - private static final boolean ALLOW_THIRD_PARTY_EARS = GeyserImpl.getInstance().getConfig().isAllowThirdPartyEars(); - private static final String EARS_GEOMETRY; - private static final String EARS_GEOMETRY_SLIM; static final SkinGeometry SKULL_GEOMETRY; static final SkinGeometry WEARING_CUSTOM_SKULL; static final SkinGeometry WEARING_CUSTOM_SKULL_SLIM; @@ -114,28 +114,27 @@ public class SkinProvider { outputStream.write((rgba >> 24) & 0xFF); // Alpha } } - EMPTY_SKIN = new Skin(-1, "geysermc:empty", outputStream.toByteArray()); - - /* Load in the normal ears geometry */ - EARS_GEOMETRY = new String(FileUtils.readAllBytes("bedrock/skin/geometry.humanoid.ears.json"), StandardCharsets.UTF_8); - - /* Load in the slim ears geometry */ - EARS_GEOMETRY_SLIM = new String(FileUtils.readAllBytes("bedrock/skin/geometry.humanoid.earsSlim.json"), StandardCharsets.UTF_8); + EMPTY_SKIN = new Skin("geysermc:empty", outputStream.toByteArray(), true); /* Load in the custom skull geometry */ String skullData = new String(FileUtils.readAllBytes("bedrock/skin/geometry.humanoid.customskull.json"), StandardCharsets.UTF_8); - SKULL_GEOMETRY = new SkinGeometry("{\"geometry\" :{\"default\" :\"geometry.humanoid.customskull\"}}", skullData, false); + SKULL_GEOMETRY = new SkinGeometry("{\"geometry\" :{\"default\" :\"geometry.humanoid.customskull\"}}", skullData); /* Load in the player head skull geometry */ String wearingCustomSkull = new String(FileUtils.readAllBytes("bedrock/skin/geometry.humanoid.wearingCustomSkull.json"), StandardCharsets.UTF_8); - WEARING_CUSTOM_SKULL = new SkinGeometry("{\"geometry\" :{\"default\" :\"geometry.humanoid.wearingCustomSkull\"}}", wearingCustomSkull, false); + WEARING_CUSTOM_SKULL = new SkinGeometry("{\"geometry\" :{\"default\" :\"geometry.humanoid.wearingCustomSkull\"}}", wearingCustomSkull); String wearingCustomSkullSlim = new String(FileUtils.readAllBytes("bedrock/skin/geometry.humanoid.wearingCustomSkullSlim.json"), StandardCharsets.UTF_8); - WEARING_CUSTOM_SKULL_SLIM = new SkinGeometry("{\"geometry\" :{\"default\" :\"geometry.humanoid.wearingCustomSkullSlim\"}}", wearingCustomSkullSlim, false); + WEARING_CUSTOM_SKULL_SLIM = new SkinGeometry("{\"geometry\" :{\"default\" :\"geometry.humanoid.wearingCustomSkullSlim\"}}", wearingCustomSkullSlim); + + GeyserImpl geyser = GeyserImpl.getInstance(); + if (geyser.getConfig().isAllowThirdPartyEars() || geyser.getConfig().isAllowThirdPartyCapes()) { + geyser.getLogger().warning("Third-party ears/capes have been removed from Geyser, if you still wish to have this functionality please use the extension: https://github.com/GeyserMC/ThirdPartyCosmetics"); + } } public static ExecutorService getExecutorService() { if (EXECUTOR_SERVICE == null) { - EXECUTOR_SERVICE = Executors.newFixedThreadPool(ALLOW_THIRD_PARTY_CAPES ? 21 : 14); + EXECUTOR_SERVICE = Executors.newFixedThreadPool(14); } return EXECUTOR_SERVICE; } @@ -204,7 +203,7 @@ public class SkinProvider { // We don't have a skin for the player right now. Fall back to a default. ProvidedSkins.ProvidedSkin providedSkin = ProvidedSkins.getDefaultPlayerSkin(uuid); skin = providedSkin.getData(); - geometry = providedSkin.isSlim() ? SkinProvider.SkinGeometry.SLIM : SkinProvider.SkinGeometry.WIDE; + geometry = providedSkin.isSlim() ? SkinGeometry.SLIM : SkinGeometry.WIDE; } if (cape == null) { @@ -238,7 +237,7 @@ public class SkinProvider { return CACHED_JAVA_CAPES.getIfPresent(capeUrl); } - static CompletableFuture requestSkinData(PlayerEntity entity) { + static CompletableFuture requestSkinData(PlayerEntity entity, GeyserSession session) { SkinManager.GameProfileData data = SkinManager.GameProfileData.from(entity); if (data == null) { // This player likely does not have a textures property @@ -260,42 +259,33 @@ public class SkinProvider { cape = getCachedBedrockCape(entity.getUuid()); } - if (cape.failed() && ALLOW_THIRD_PARTY_CAPES) { - cape = getOrDefault(requestUnofficialCape( - cape, entity.getUuid(), - entity.getUsername(), false - ), EMPTY_CAPE, CapeProvider.VALUES.length * 3); - } - - boolean isDeadmau5 = "deadmau5".equals(entity.getUsername()); - // Not a bedrock player check for ears - if (geometry.failed() && (ALLOW_THIRD_PARTY_EARS || isDeadmau5)) { - boolean isEars; - - // Its deadmau5, gotta support his skin :) - if (isDeadmau5) { - isEars = true; - } else { - // Get the ears texture for the player - skin = getOrDefault(requestUnofficialEars( - skin, entity.getUuid(), entity.getUsername(), false - ), skin, 3); - - isEars = skin.isEars(); + // Call event to allow extensions to modify the skin, cape and geo + boolean isBedrock = GeyserImpl.getInstance().connectionByUuid(entity.getUuid()) != null; + SkinData skinData = new SkinData(skin, cape, geometry); + final EventSkinData eventSkinData = new EventSkinData(skinData); + GeyserImpl.getInstance().eventBus().fire(new SessionSkinApplyEvent(session, entity.getUsername(), entity.getUuid(), data.isAlex(), isBedrock, skinData) { + @Override + public SkinData skinData() { + return eventSkinData.skinData(); } - // Does the skin have an ears texture - if (isEars) { - // Get the new geometry - geometry = SkinGeometry.getEars(data.isAlex()); - - // Store the skin and geometry for the ears - storeEarSkin(skin); - storeEarGeometry(entity.getUuid(), data.isAlex()); + @Override + public void skin(@NonNull Skin newSkin) { + eventSkinData.skinData(new SkinData(Objects.requireNonNull(newSkin), skinData.cape(), skinData.geometry())); } - } - return new SkinData(skin, cape, geometry); + @Override + public void cape(@NonNull Cape newCape) { + eventSkinData.skinData(new SkinData(skinData.skin(), Objects.requireNonNull(newCape), skinData.geometry())); + } + + @Override + public void geometry(@NonNull SkinGeometry newGeometry) { + eventSkinData.skinData(new SkinData(skinData.skin(), skinData.cape(), Objects.requireNonNull(newGeometry))); + } + }); + + return eventSkinData.skinData(); } catch (Exception e) { GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.skin.fail", entity.getUuid()), e); } @@ -308,10 +298,9 @@ public class SkinProvider { return CompletableFuture.supplyAsync(() -> { long time = System.currentTimeMillis(); - CapeProvider provider = capeUrl != null ? CapeProvider.MINECRAFT : null; SkinAndCape skinAndCape = new SkinAndCape( getOrDefault(requestSkin(playerId, skinUrl, false), EMPTY_SKIN, 5), - getOrDefault(requestCape(capeUrl, provider, false), EMPTY_CAPE, 5) + getOrDefault(requestCape(capeUrl, false), EMPTY_CAPE, 5) ); GeyserImpl.getInstance().getLogger().debug("Took " + (System.currentTimeMillis() - time) + "ms for " + playerId); @@ -336,7 +325,6 @@ public class SkinProvider { if (newThread) { future = CompletableFuture.supplyAsync(() -> supplySkin(playerId, textureUrl), getExecutorService()) .whenCompleteAsync((skin, throwable) -> { - skin.updated = true; CACHED_JAVA_SKINS.put(textureUrl, skin); requestedSkins.remove(textureUrl); }); @@ -349,7 +337,7 @@ public class SkinProvider { return future; } - private static CompletableFuture requestCape(String capeUrl, CapeProvider provider, boolean newThread) { + private static CompletableFuture requestCape(String capeUrl, boolean newThread) { if (capeUrl == null || capeUrl.isEmpty()) return CompletableFuture.completedFuture(EMPTY_CAPE); CompletableFuture requestedCape = requestedCapes.get(capeUrl); if (requestedCape != null) { @@ -363,128 +351,48 @@ public class SkinProvider { CompletableFuture future; if (newThread) { - future = CompletableFuture.supplyAsync(() -> supplyCape(capeUrl, provider), getExecutorService()) + future = CompletableFuture.supplyAsync(() -> supplyCape(capeUrl), getExecutorService()) .whenCompleteAsync((cape, throwable) -> { CACHED_JAVA_CAPES.put(capeUrl, cape); requestedCapes.remove(capeUrl); }); requestedCapes.put(capeUrl, future); } else { - Cape cape = supplyCape(capeUrl, provider); // blocking + Cape cape = supplyCape(capeUrl); // blocking future = CompletableFuture.completedFuture(cape); CACHED_JAVA_CAPES.put(capeUrl, cape); } return future; } - private static CompletableFuture requestUnofficialCape(Cape officialCape, UUID playerId, - String username, boolean newThread) { - if (officialCape.failed() && ALLOW_THIRD_PARTY_CAPES) { - for (CapeProvider provider : CapeProvider.VALUES) { - if (provider.type != CapeUrlType.USERNAME && IS_NPC.test(playerId)) { - continue; - } - - Cape cape1 = getOrDefault( - requestCape(provider.getUrlFor(playerId, username), provider, newThread), - EMPTY_CAPE, 4 - ); - if (!cape1.failed()) { - return CompletableFuture.completedFuture(cape1); - } - } - } - return CompletableFuture.completedFuture(officialCape); - } - - private static CompletableFuture requestEars(String earsUrl, boolean newThread, Skin skin) { - if (earsUrl == null || earsUrl.isEmpty()) return CompletableFuture.completedFuture(skin); - - CompletableFuture future; - if (newThread) { - future = CompletableFuture.supplyAsync(() -> supplyEars(skin, earsUrl), getExecutorService()) - .whenCompleteAsync((outSkin, throwable) -> { }); - } else { - Skin ears = supplyEars(skin, earsUrl); // blocking - future = CompletableFuture.completedFuture(ears); - } - return future; - } - - /** - * Try and find an ear texture for a Java player - * - * @param officialSkin The current players skin - * @param playerId The players UUID - * @param username The players username - * @param newThread Should we start in a new thread - * @return The updated skin with ears - */ - private static CompletableFuture requestUnofficialEars(Skin officialSkin, UUID playerId, String username, boolean newThread) { - for (EarsProvider provider : EarsProvider.VALUES) { - if (provider.type != CapeUrlType.USERNAME && IS_NPC.test(playerId)) { - continue; - } - - Skin skin1 = getOrDefault( - requestEars(provider.getUrlFor(playerId, username), newThread, officialSkin), - officialSkin, 4 - ); - if (skin1.isEars()) { - return CompletableFuture.completedFuture(skin1); - } - } - - return CompletableFuture.completedFuture(officialSkin); - } - static void storeBedrockSkin(UUID playerID, String skinId, byte[] skinData) { - Skin skin = new Skin(playerID, skinId, skinData, System.currentTimeMillis(), true, false); - CACHED_BEDROCK_SKINS.put(skin.getTextureUrl(), skin); + Skin skin = new Skin(skinId, skinData); + CACHED_BEDROCK_SKINS.put(skin.textureUrl(), skin); } static void storeBedrockCape(String capeId, byte[] capeData) { - Cape cape = new Cape(capeId, capeId, capeData, System.currentTimeMillis(), false); + Cape cape = new Cape(capeId, capeId, capeData); CACHED_BEDROCK_CAPES.put(capeId, cape); } static void storeBedrockGeometry(UUID playerID, byte[] geometryName, byte[] geometryData) { - SkinGeometry geometry = new SkinGeometry(new String(geometryName), new String(geometryData), false); + SkinGeometry geometry = new SkinGeometry(new String(geometryName), new String(geometryData)); cachedGeometry.put(playerID, geometry); } - /** - * Stores the adjusted skin with the ear texture to the cache - * - * @param skin The skin to cache - */ - public static void storeEarSkin(Skin skin) { - CACHED_JAVA_SKINS.put(skin.getTextureUrl(), skin); - } - - /** - * Stores the geometry for a Java player with ears - * - * @param playerID The UUID to cache it against - * @param isSlim If the player is using an slim base - */ - private static void storeEarGeometry(UUID playerID, boolean isSlim) { - cachedGeometry.put(playerID, SkinGeometry.getEars(isSlim)); - } - private static Skin supplySkin(UUID uuid, String textureUrl) { try { - byte[] skin = requestImageData(textureUrl, null); - return new Skin(uuid, textureUrl, skin, System.currentTimeMillis(), false, false); + byte[] skin = requestImageData(textureUrl, false); + return new Skin(textureUrl, skin); } catch (Exception ignored) {} // just ignore I guess - return new Skin(uuid, "empty", EMPTY_SKIN.getSkinData(), System.currentTimeMillis(), false, false); + return new Skin("empty", EMPTY_SKIN.skinData(), true); } - private static Cape supplyCape(String capeUrl, CapeProvider provider) { + private static Cape supplyCape(String capeUrl) { byte[] cape = EMPTY_CAPE.capeData(); try { - cape = requestImageData(capeUrl, provider); + cape = requestImageData(capeUrl, true); } catch (Exception ignored) { } // just ignore I guess @@ -494,54 +402,12 @@ public class SkinProvider { capeUrl, urlSection[urlSection.length - 1], // get the texture id and use it as cape id cape, - System.currentTimeMillis(), cape.length == 0 ); } - /** - * Get the ears texture and place it on the skin from the given URL - * - * @param existingSkin The players current skin - * @param earsUrl The URL to get the ears texture from - * @return The updated skin with ears - */ - private static Skin supplyEars(Skin existingSkin, String earsUrl) { - try { - // Get the ears texture - BufferedImage ears = ImageIO.read(new URL(earsUrl)); - if (ears == null) throw new NullPointerException(); - - // Convert the skin data to a BufferedImage - int height = (existingSkin.getSkinData().length / 4 / 64); - BufferedImage skinImage = imageDataToBufferedImage(existingSkin.getSkinData(), 64, height); - - // Create a new image with the ears texture over it - BufferedImage newSkin = new BufferedImage(skinImage.getWidth(), skinImage.getHeight(), BufferedImage.TYPE_INT_ARGB); - Graphics2D g = (Graphics2D) newSkin.getGraphics(); - g.drawImage(skinImage, 0, 0, null); - g.drawImage(ears, 24, 0, null); - - // Turn the buffered image back into an array of bytes - byte[] data = bufferedImageToImageData(newSkin); - skinImage.flush(); - - // Create a new skin object with the new infomation - return new Skin( - existingSkin.getSkinOwner(), - existingSkin.getTextureUrl(), - data, - System.currentTimeMillis(), - true, - true - ); - } catch (Exception ignored) {} // just ignore I guess - - return existingSkin; - } - @SuppressWarnings("ResultOfMethodCallIgnored") - public static BufferedImage requestImage(String imageUrl, CapeProvider provider) throws IOException { + public static BufferedImage requestImage(String imageUrl, boolean isCape) 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 @@ -556,7 +422,7 @@ public class SkinProvider { // If no image we download it if (image == null) { - image = downloadImage(imageUrl, provider); + image = downloadImage(imageUrl); GeyserImpl.getInstance().getLogger().debug("Downloaded " + imageUrl); // Write to cache if we are allowed @@ -572,7 +438,7 @@ public class SkinProvider { } // if the requested image is a cape - if (provider != null) { + if (isCape) { if (image.getWidth() > 64 || image.getHeight() > 32) { // Prevent weirdly-scaled capes from being cut off BufferedImage newImage = new BufferedImage(128, 64, BufferedImage.TYPE_INT_ARGB); @@ -604,8 +470,8 @@ public class SkinProvider { return image; } - private static byte[] requestImageData(String imageUrl, CapeProvider provider) throws Exception { - BufferedImage image = requestImage(imageUrl, provider); + private static byte[] requestImageData(String imageUrl, boolean isCape) throws Exception { + BufferedImage image = requestImage(imageUrl, isCape); byte[] data = bufferedImageToImageData(image); image.flush(); return data; @@ -668,35 +534,20 @@ public class SkinProvider { }); } - private static BufferedImage downloadImage(String imageUrl, CapeProvider provider) throws IOException { - BufferedImage image; - if (provider == CapeProvider.FIVEZIG) { - image = readFiveZigCape(imageUrl); - } else { - HttpURLConnection con = (HttpURLConnection) new URL(imageUrl).openConnection(); - con.setRequestProperty("User-Agent", WebUtils.getUserAgent()); - con.setConnectTimeout(10000); - con.setReadTimeout(10000); + private static BufferedImage downloadImage(String imageUrl) throws IOException { + HttpURLConnection con = (HttpURLConnection) new URL(imageUrl).openConnection(); + con.setRequestProperty("User-Agent", WebUtils.getUserAgent()); + con.setConnectTimeout(10000); + con.setReadTimeout(10000); - image = ImageIO.read(con.getInputStream()); - } + BufferedImage image = ImageIO.read(con.getInputStream()); if (image == null) { - throw new IllegalArgumentException("Failed to read image from: %s (cape provider=%s)".formatted(imageUrl, provider)); + throw new IllegalArgumentException("Failed to read image from: %s".formatted(imageUrl)); } return image; } - 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"); - if (capeElement == null || capeElement.isNull()) return null; - return ImageIO.read(new ByteArrayInputStream(Base64.getDecoder().decode(capeElement.textValue()))); - } - return null; - } - public static BufferedImage scale(BufferedImage bufferedImage, int newWidth, int newHeight) { BufferedImage resized = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = resized.createGraphics(); @@ -770,124 +621,19 @@ public class SkinProvider { public record SkinAndCape(Skin skin, Cape cape) { } - /** - * Represents a full package of skin, cape, and geometry. - */ - public record SkinData(Skin skin, Cape cape, SkinGeometry geometry) { - } + public static class EventSkinData { + private SkinData skinData; - @AllArgsConstructor - @Getter - public static class Skin { - private UUID skinOwner; - private final String textureUrl; - private final byte[] skinData; - private final long requestedOn; - private boolean updated; - private boolean ears; + public EventSkinData(SkinData skinData) { + this.skinData = skinData; + } - Skin(long requestedOn, String textureUrl, byte[] skinData) { - this.requestedOn = requestedOn; - this.textureUrl = textureUrl; + public SkinData skinData() { + return skinData; + } + + public void skinData(SkinData skinData) { this.skinData = skinData; } } - - public record Cape(String textureUrl, String capeId, byte[] capeData, long requestedOn, boolean failed) { - } - - public record SkinGeometry(String geometryName, String geometryData, boolean failed) { - public static SkinGeometry WIDE = getLegacy(false); - public static SkinGeometry SLIM = getLegacy(true); - - /** - * Generate generic geometry - * - * @param isSlim Should it be the alex model - * @return The generic geometry object - */ - private static SkinGeometry getLegacy(boolean isSlim) { - return new SkinProvider.SkinGeometry("{\"geometry\" :{\"default\" :\"geometry.humanoid.custom" + (isSlim ? "Slim" : "") + "\"}}", "", true); - } - - /** - * Generate basic geometry with ears - * - * @param isSlim Should it be the alex model - * @return The generated geometry for the ears model - */ - private static SkinGeometry getEars(boolean isSlim) { - return new SkinProvider.SkinGeometry("{\"geometry\" :{\"default\" :\"geometry.humanoid.ears" + (isSlim ? "Slim" : "") + "\"}}", (isSlim ? EARS_GEOMETRY_SLIM : EARS_GEOMETRY), false); - } - } - - /* - * Sorted by 'priority' - */ - @AllArgsConstructor - @NoArgsConstructor - @Getter - public enum CapeProvider { - MINECRAFT, - OPTIFINE("https://optifine.net/capes/%s.png", CapeUrlType.USERNAME), - LABYMOD("https://dl.labymod.net/capes/%s", CapeUrlType.UUID_DASHED), - FIVEZIG("https://textures.5zigreborn.eu/profile/%s", CapeUrlType.UUID_DASHED), - MINECRAFTCAPES("https://api.minecraftcapes.net/profile/%s/cape", CapeUrlType.UUID); - - public static final CapeProvider[] VALUES = Arrays.copyOfRange(values(), 1, 5); - private String url; - private CapeUrlType type; - - public String getUrlFor(String type) { - return String.format(url, type); - } - - public String getUrlFor(UUID uuid, String username) { - return getUrlFor(toRequestedType(type, uuid, username)); - } - - public static String toRequestedType(CapeUrlType type, UUID uuid, String username) { - return switch (type) { - case UUID -> uuid.toString().replace("-", ""); - case UUID_DASHED -> uuid.toString(); - default -> username; - }; - } - } - - public enum CapeUrlType { - USERNAME, - UUID, - UUID_DASHED - } - - /* - * Sorted by 'priority' - */ - @AllArgsConstructor - @NoArgsConstructor - @Getter - public enum EarsProvider { - MINECRAFTCAPES("https://api.minecraftcapes.net/profile/%s/ears", CapeUrlType.UUID); - - public static final EarsProvider[] VALUES = values(); - private String url; - private CapeUrlType type; - - public String getUrlFor(String type) { - return String.format(url, type); - } - - public String getUrlFor(UUID uuid, String username) { - return getUrlFor(toRequestedType(type, uuid, username)); - } - - public static String toRequestedType(CapeUrlType type, UUID uuid, String username) { - return switch (type) { - case UUID -> uuid.toString().replace("-", ""); - case UUID_DASHED -> uuid.toString(); - default -> username; - }; - } - } } diff --git a/core/src/main/java/org/geysermc/geyser/skin/SkullSkinManager.java b/core/src/main/java/org/geysermc/geyser/skin/SkullSkinManager.java index 18edc8079..e3f00d3b7 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/SkullSkinManager.java +++ b/core/src/main/java/org/geysermc/geyser/skin/SkullSkinManager.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 @@ -29,6 +29,8 @@ import org.cloudburstmc.protocol.bedrock.data.skin.ImageData; import org.cloudburstmc.protocol.bedrock.data.skin.SerializedSkin; import org.cloudburstmc.protocol.bedrock.packet.PlayerSkinPacket; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.skin.Skin; +import org.geysermc.geyser.api.skin.SkinData; import org.geysermc.geyser.entity.type.player.SkullPlayerEntity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; @@ -50,14 +52,14 @@ public class SkullSkinManager extends SkinManager { } public static void requestAndHandleSkin(SkullPlayerEntity entity, GeyserSession session, - Consumer skinConsumer) { - BiConsumer applySkin = (skin, throwable) -> { + Consumer skinConsumer) { + BiConsumer applySkin = (skin, throwable) -> { try { PlayerSkinPacket packet = new PlayerSkinPacket(); packet.setUuid(entity.getUuid()); packet.setOldSkinName(""); - packet.setNewSkinName(skin.getTextureUrl()); - packet.setSkin(buildSkullEntryManually(skin.getTextureUrl(), skin.getSkinData())); + packet.setNewSkinName(skin.textureUrl()); + packet.setSkin(buildSkullEntryManually(skin.textureUrl(), skin.skinData())); packet.setTrustedSkin(true); session.sendUpstreamPacket(packet); } catch (Exception e) { @@ -74,7 +76,7 @@ public class SkullSkinManager extends SkinManager { GeyserImpl.getInstance().getLogger().debug("Using fallback skin for skull at " + entity.getSkullPosition() + " with texture value: " + entity.getTexturesProperty() + " and UUID: " + entity.getSkullUUID()); // No texture available, fallback using the UUID - SkinProvider.SkinData fallback = SkinProvider.determineFallbackSkinData(entity.getSkullUUID()); + SkinData fallback = SkinProvider.determineFallbackSkinData(entity.getSkullUUID()); applySkin.accept(fallback.skin(), null); } else { SkinProvider.requestSkin(entity.getUuid(), data.skinUrl(), true) diff --git a/core/src/main/resources/bedrock/skin/geometry.humanoid.ears.json b/core/src/main/resources/bedrock/skin/geometry.humanoid.ears.json deleted file mode 100644 index 5571655b8..000000000 --- a/core/src/main/resources/bedrock/skin/geometry.humanoid.ears.json +++ /dev/null @@ -1,249 +0,0 @@ -{ - "format_version": "1.14.0", - "minecraft:geometry": [ - { - "bones": [ - { - "name" : "root", - "pivot" : [ 0.0, 0.0, 0.0 ] - }, - - { - "name" : "waist", - "parent" : "root", - "pivot" : [ 0.0, 12.0, 0.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes" : [] - }, - - - { - "name": "body", - "parent" : "waist", - "pivot": [ 0.0, 24.0, 0.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes": [ - { - "origin": [ -4.0, 12.0, -2.0 ], - "size": [ 8, 12, 4 ], - "uv": [ 16, 16 ] - } - ] - }, - - { - "name": "jacket", - "parent" : "body", - "pivot": [ 0.0, 24.0, 0.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes": [ - { - "origin": [ -4.0, 12.0, -2.0 ], - "size": [ 8, 12, 4 ], - "uv": [ 16, 32 ], - "inflate": 0.25 - } - ] - }, - - - { - "name": "head", - "parent" : "body", - "pivot": [ 0.0, 24.0, 0.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes": [ - { - "origin": [ -4.0, 24.0, -4.0 ], - "size": [ 8, 8, 8 ], - "uv": [ 0, 0 ] - } - ] - }, - - { - "name": "hat", - "parent" : "head", - "pivot": [ 0.0, 24.0, 0.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes": [ - { - "origin": [ -4.0, 24.0, -4.0 ], - "size": [ 8, 8, 8 ], - "uv": [ 32, 0 ], - "inflate": 0.5 - } - ] - }, - - - { - "name": "leftArm", - "parent" : "body", - "pivot": [ 5.0, 22.0, 0.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes": [ - { - "origin": [ 4.0, 12.0, -2.0 ], - "size": [ 4, 12, 4 ], - "uv": [ 32, 48 ] - } - ] - }, - { - "name": "rightArm", - "parent" : "body", - "pivot": [ -5.0, 22.0, 0.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes": [ - { - "origin": [ -8.0, 12.0, -2.0 ], - "size": [ 4, 12, 4 ], - "uv": [ 40, 16 ] - } - ] - }, - - { - "name": "leftSleeve", - "parent" : "leftArm", - "pivot": [ 5.0, 22.0, 0.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes": [ - { - "origin": [ 4.0, 12.0, -2.0 ], - "size": [ 4, 12, 4 ], - "uv": [ 48, 48 ], - "inflate": 0.25 - } - ] - }, - - { - "name": "rightSleeve", - "parent" : "rightArm", - "pivot": [ -5.0, 22.0, 0.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes": [ - { - "origin": [ -8.0, 12.0, -2.0 ], - "size": [ 4, 12, 4 ], - "uv": [ 40, 32 ], - "inflate": 0.25 - } - ] - }, - - - { - "name": "leftLeg", - "parent" : "root", - "pivot": [ 1.9, 12.0, 0.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes": [ - { - "origin": [ -0.1, 0.0, -2.0 ], - "size": [ 4, 12, 4 ], - "uv": [ 0, 16 ] - } - ] - }, - - { - "name": "rightLeg", - "parent" : "root", - "pivot": [ -1.9, 12.0, 0.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes": [ - { - "origin": [ -3.9, 0.0, -2.0 ], - "size": [ 4, 12, 4 ], - "uv": [ 0, 16 ] - } - ] - }, - - { - "name": "leftPants", - "parent" : "leftLeg", - "pivot": [1.9, 12.0, 0.0], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes": [ - { - "origin": [ -0.1, 0.0, -2.0 ], - "size": [ 4, 12, 4 ], - "uv": [ 0, 48 ], - "inflate": 0.25 - } - ] - }, - - { - "name": "rightPants", - "parent" : "rightLeg", - "pivot": [ -1.9, 12.0, 0.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes": [ - { - "origin": [ -3.9, 0.0, -2.0] , - "size": [ 4, 12, 4 ], - "uv": [ 0, 32], - "inflate": 0.25 - } - ] - }, - - - { - "name" : "rightItem", - "parent" : "rightArm", - "pivot" : [ -6.0, 15.0, 1.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes" : [] - }, - - { - "name" : "leftItem", - "parent" : "leftArm", - "pivot" : [ 6.0, 15.0, 1.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes" : [] - }, - - - { - "name": "leftEar", - "parent" : "head", - "pivot": [ -1.9, 12.0, 0.0 ], - "cubes": [ - { - "origin": [ 3.0, 31.0, -0.5 ], - "size": [ 6, 6, 1 ], - "uv": [ 24, 0 ], - "inflate": 0.5 - } - ] - }, - - { - "name": "rightEar", - "parent" : "head", - "pivot": [ -1.9, 12.0, 0.0 ], - "cubes": [ - { - "origin": [ -9.0, 31.0, -0.5 ], - "size": [ 6, 6, 1 ], - "uv": [ 24, 0 ], - "inflate": 0.5 - } - ] - } - ], - "description": { - "identifier": "geometry.humanoid.ears", - "texture_height": 64, - "texture_width": 64 - } - } - ] -} \ No newline at end of file diff --git a/core/src/main/resources/bedrock/skin/geometry.humanoid.earsSlim.json b/core/src/main/resources/bedrock/skin/geometry.humanoid.earsSlim.json deleted file mode 100644 index 70c44f854..000000000 --- a/core/src/main/resources/bedrock/skin/geometry.humanoid.earsSlim.json +++ /dev/null @@ -1,249 +0,0 @@ -{ - "format_version": "1.14.0", - "minecraft:geometry": [ - { - "bones": [ - { - "name" : "root", - "pivot" : [ 0.0, 0.0, 0.0 ] - }, - - { - "name" : "waist", - "parent" : "root", - "pivot" : [ 0.0, 12.0, 0.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes" : [] - }, - - - { - "name": "body", - "parent" : "waist", - "pivot": [ 0.0, 24.0, 0.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes": [ - { - "origin": [ -4.0, 12.0, -2.0 ], - "size": [ 8, 12, 4 ], - "uv": [ 16, 16 ] - } - ] - }, - - { - "name": "jacket", - "parent" : "body", - "pivot": [ 0.0, 24.0, 0.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes": [ - { - "origin": [ -4.0, 12.0, -2.0 ], - "size": [ 8, 12, 4 ], - "uv": [ 16, 32 ], - "inflate": 0.25 - } - ] - }, - - - { - "name": "head", - "parent" : "body", - "pivot": [ 0.0, 24.0, 0.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes": [ - { - "origin": [ -4.0, 24.0, -4.0 ], - "size": [ 8, 8, 8 ], - "uv": [ 0, 0 ] - } - ] - }, - - { - "name": "hat", - "parent" : "head", - "pivot": [ 0.0, 24.0, 0.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes": [ - { - "origin": [ -4.0, 24.0, -4.0 ], - "size": [ 8, 8, 8 ], - "uv": [ 32, 0 ], - "inflate": 0.5 - } - ] - }, - - - { - "name": "leftArm", - "parent" : "body", - "pivot": [ 5.0, 21.5, 0.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes": [ - { - "origin": [ 4.0, 12, -2.0 ], - "size": [ 3, 12, 4 ], - "uv": [ 32, 48 ] - } - ] - }, - { - "name": "rightArm", - "parent" : "body", - "pivot": [ -5.0, 21.5, 0.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes": [ - { - "origin": [ -7.0, 12, -2.0 ], - "size": [ 3, 12, 4 ], - "uv": [ 40, 16 ] - } - ] - }, - - { - "name": "leftSleeve", - "parent" : "leftArm", - "pivot": [ 5.0, 21.5, 0.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes": [ - { - "origin": [ 4.0, 11.5, -2.0 ], - "size": [ 3, 12, 4 ], - "uv": [ 48, 48 ], - "inflate": 0.25 - } - ] - }, - - { - "name": "rightSleeve", - "parent" : "rightArm", - "pivot": [ -5.0, 21.5, 0.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes": [ - { - "origin": [ -7.0, 11.5, -2.0 ], - "size": [ 3, 12, 4 ], - "uv": [ 40, 32 ], - "inflate": 0.25 - } - ] - }, - - - { - "name": "leftLeg", - "parent" : "root", - "pivot": [ 1.9, 12.0, 0.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes": [ - { - "origin": [ -0.1, 0.0, -2.0 ], - "size": [ 4, 12, 4 ], - "uv": [ 0, 16 ] - } - ] - }, - - { - "name": "rightLeg", - "parent" : "root", - "pivot": [ -1.9, 12.0, 0.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes": [ - { - "origin": [ -3.9, 0.0, -2.0 ], - "size": [ 4, 12, 4 ], - "uv": [ 0, 16 ] - } - ] - }, - - { - "name": "leftPants", - "parent" : "leftLeg", - "pivot": [1.9, 12.0, 0.0], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes": [ - { - "origin": [ -0.1, 0.0, -2.0 ], - "size": [ 4, 12, 4 ], - "uv": [ 0, 48 ], - "inflate": 0.25 - } - ] - }, - - { - "name": "rightPants", - "parent" : "rightLeg", - "pivot": [ -1.9, 12.0, 0.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes": [ - { - "origin": [ -3.9, 0.0, -2.0] , - "size": [ 4, 12, 4 ], - "uv": [ 0, 32], - "inflate": 0.25 - } - ] - }, - - - { - "name" : "rightItem", - "parent" : "rightArm", - "pivot" : [ -6.0, 15.0, 1.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes" : [] - }, - - { - "name" : "leftItem", - "parent" : "leftArm", - "pivot" : [ 6.0, 15.0, 1.0 ], - "rotation" : [ 0.0, 0.0, 0.0 ], - "cubes" : [] - }, - - - { - "name": "leftEar", - "parent" : "head", - "pivot": [ -1.9, 12.0, 0.0 ], - "cubes": [ - { - "origin": [ 3.0, 31.0, -0.5 ], - "size": [ 6, 6, 1 ], - "uv": [ 24, 0 ], - "inflate": 0.5 - } - ] - }, - - { - "name": "rightEar", - "parent" : "head", - "pivot": [ -1.9, 12.0, 0.0 ], - "cubes": [ - { - "origin": [ -9.0, 31.0, -0.5 ], - "size": [ 6, 6, 1 ], - "uv": [ 24, 0 ], - "inflate": 0.5 - } - ] - } - ], - "description": { - "identifier": "geometry.humanoid.earsSlim", - "texture_height": 64, - "texture_width": 64 - } - } - ] -} \ No newline at end of file diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index c70b0d7ab..fc0cd83f1 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -113,14 +113,6 @@ max-players: 100 # If debug messages should be sent through console debug-mode: false -# Allow third party capes to be visible. Currently allowing: -# OptiFine capes, LabyMod capes, 5Zig capes and MinecraftCapes -allow-third-party-capes: false - -# Allow third party deadmau5 ears to be visible. Currently allowing: -# MinecraftCapes -allow-third-party-ears: false - # Allow a fake cooldown indicator to be sent. Bedrock players otherwise do not see a cooldown as they still use 1.8 combat. # Please note: if the cooldown is enabled, some users may see a black box during the cooldown sequence, like below: # https://cdn.discordapp.com/attachments/613170125696270357/957075682230419466/Screenshot_from_2022-03-25_20-35-08.png diff --git a/gradle.properties b/gradle.properties index dd61d2556..40d8a36db 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,5 +7,5 @@ org.gradle.vfs.watch=false group=org.geysermc id=geyser -version=2.3.0-SNAPSHOT +version=2.3.1-SNAPSHOT description=Allows for players from Minecraft: Bedrock Edition to join Minecraft: Java Edition servers. From 4d61766d0adf17849ecd66538c3889f76a763b3f Mon Sep 17 00:00:00 2001 From: rtm516 Date: Tue, 14 May 2024 16:38:51 +0100 Subject: [PATCH 005/233] Fix SessionSkinApplyEvent not keeping altered skin data (#4663) --- .../main/java/org/geysermc/geyser/skin/SkinProvider.java | 6 +++--- 1 file changed, 3 insertions(+), 3 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 3b31dfff8..5b16bc3a3 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java +++ b/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java @@ -271,17 +271,17 @@ public class SkinProvider { @Override public void skin(@NonNull Skin newSkin) { - eventSkinData.skinData(new SkinData(Objects.requireNonNull(newSkin), skinData.cape(), skinData.geometry())); + eventSkinData.skinData(new SkinData(Objects.requireNonNull(newSkin), eventSkinData.skinData().cape(), eventSkinData.skinData().geometry())); } @Override public void cape(@NonNull Cape newCape) { - eventSkinData.skinData(new SkinData(skinData.skin(), Objects.requireNonNull(newCape), skinData.geometry())); + eventSkinData.skinData(new SkinData(eventSkinData.skinData().skin(), Objects.requireNonNull(newCape), eventSkinData.skinData().geometry())); } @Override public void geometry(@NonNull SkinGeometry newGeometry) { - eventSkinData.skinData(new SkinData(skinData.skin(), skinData.cape(), Objects.requireNonNull(newGeometry))); + eventSkinData.skinData(new SkinData(eventSkinData.skinData().skin(), eventSkinData.skinData().cape(), Objects.requireNonNull(newGeometry))); } }); From 6c4b2cb173bb5e36396a3ee031286ee2ab3f8ed4 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Wed, 15 May 2024 13:40:57 -0400 Subject: [PATCH 006/233] Don't create a property manager if an entity has no properties --- .../geysermc/geyser/entity/type/Entity.java | 4 +- .../java/JavaSelectKnownPacksTranslator.java | 62 +++++++++++++++++++ 2 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSelectKnownPacksTranslator.java 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 fecd72f67..da9a28451 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 @@ -134,7 +134,7 @@ public class Entity implements GeyserEntity { this.valid = false; - this.propertyManager = new GeyserEntityPropertyManager(definition.registeredProperties()); + this.propertyManager = definition.registeredProperties() == null ? null : new GeyserEntityPropertyManager(definition.registeredProperties()); setPosition(position); setAirSupply(getMaxAir()); @@ -361,7 +361,7 @@ public class Entity implements GeyserEntity { return; } - if (propertyManager.hasProperties()) { + if (propertyManager != null && propertyManager.hasProperties()) { SetEntityDataPacket entityDataPacket = new SetEntityDataPacket(); entityDataPacket.setRuntimeEntityId(geyserId); propertyManager.applyIntProperties(entityDataPacket.getProperties().getIntProperties()); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSelectKnownPacksTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSelectKnownPacksTranslator.java new file mode 100644 index 000000000..6b1c8c645 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSelectKnownPacksTranslator.java @@ -0,0 +1,62 @@ +/* + * 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; + +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 org.geysermc.mcprotocollib.protocol.data.game.KnownPack; +import org.geysermc.mcprotocollib.protocol.packet.configuration.clientbound.ClientboundSelectKnownPacks; +import org.geysermc.mcprotocollib.protocol.packet.configuration.serverbound.ServerboundSelectKnownPacks; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +@Translator(packet = ClientboundSelectKnownPacks.class) +public class JavaSelectKnownPacksTranslator extends PacketTranslator { + // todo: dump from client? + private static final Set KNOWN_PACK_IDS = Set.of("core", "update_1_21", "bundle", "trade_rebalance"); + + @Override + public void translate(GeyserSession session, ClientboundSelectKnownPacks packet) { + List knownPacks = new ArrayList<>(1); + for (KnownPack pack : packet.getKnownPacks()) { + if ("minecraft".equals(pack.getNamespace()) && GameProtocol.getJavaMinecraftVersion().equals(pack.getVersion())) { + // Implementation note: these won't always necessarily be equal. + // 1.20.5 versus 1.20.6 for example - same protocol version. A vanilla server for either version will gracefully accept either. + // If the versions mismatch, the registry will be sent over the network, though. + // For vanilla compliancy, to minimize network traffic, and for potential future behavior, + // We'll implement how the Java client does it. + if (KNOWN_PACK_IDS.contains(pack.getId())) { + knownPacks.add(pack); + } + } + } + session.sendDownstreamPacket(new ServerboundSelectKnownPacks(knownPacks)); + } +} From 423d2e3a362ccd0cbf5dc0eafaed4b67d3728757 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Wed, 15 May 2024 13:41:31 -0400 Subject: [PATCH 007/233] Emulate vanilla behavior with existing registries --- .../geyser/session/GeyserSession.java | 88 ++++++++++++------- .../geyser/session/cache/RegistryCache.java | 37 +++++++- 2 files changed, 90 insertions(+), 35 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 617087f71..c0ff1fb71 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,6 @@ 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 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; @@ -145,6 +116,38 @@ 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.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 org.geysermc.mcprotocollib.protocol.ClientListener; +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.configuration.clientbound.ClientboundFinishConfigurationPacket; +import org.geysermc.mcprotocollib.protocol.packet.configuration.serverbound.ServerboundFinishConfigurationPacket; +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 java.net.ConnectException; import java.net.InetSocketAddress; @@ -646,9 +649,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { 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()); - if (GeyserImpl.getInstance().getConfig().isAddNonBedrockItems()) { ItemComponentPacket componentPacket = new ItemComponentPacket(); componentPacket.getItems().addAll(itemMappings.getComponentItemData()); @@ -875,6 +875,8 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { // Start ticking tickThread = eventLoop.scheduleAtFixedRate(this::tick, 50, 50, TimeUnit.MILLISECONDS); + this.protocol.setUseDefaultListeners(false); + TcpSession downstream; if (geyser.getBootstrap().getSocketAddress() != null) { // We're going to connect through the JVM and not through TCP @@ -904,6 +906,25 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { // Let Geyser handle sending the keep alive downstream.setFlag(MinecraftConstants.AUTOMATIC_KEEP_ALIVE_MANAGEMENT, false); } + // We'll handle this since we have the registry data on hand + downstream.setFlag(MinecraftConstants.SEND_BLANK_KNOWN_PACKS_RESPONSE, false); + + // This isn't a great solution, but... we want to make sure the finish configuration packet cannot be sent + // before the KnownPacks packet. + this.downstream.getSession().addListener(new ClientListener(ProtocolState.LOGIN, loginEvent.transferring()) { + @Override + public void packetReceived(Session session, Packet packet) { + if (protocol.getState() == ProtocolState.CONFIGURATION) { + if (packet instanceof ClientboundFinishConfigurationPacket) { + // Prevent + GeyserSession.this.ensureInEventLoop(() -> GeyserSession.this.sendDownstreamPacket(new ServerboundFinishConfigurationPacket())); + return; + } + } + super.packetReceived(session, packet); + } + }); + downstream.addListener(new SessionAdapter() { @Override public void packetSending(PacketSendingEvent event) { @@ -1543,8 +1564,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { startGamePacket.setEnchantmentSeed(0); startGamePacket.setMultiplayerCorrelationId(""); - startGamePacket.setItemDefinitions(this.itemMappings.getItemDefinitions().values().stream().toList()); // TODO - // startGamePacket.setBlockPalette(this.blockMappings.getBedrockBlockPalette()); + startGamePacket.getItemDefinitions().addAll(this.itemMappings.getItemDefinitions().values()); // Needed for custom block mappings and custom skulls system startGamePacket.getBlockProperties().addAll(this.blockMappings.getBlockProperties()); 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 9581df253..fa4503635 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 @@ -30,6 +30,8 @@ import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; import lombok.AccessLevel; import lombok.Getter; import lombok.experimental.Accessors; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.data.TrimMaterial; import org.cloudburstmc.protocol.bedrock.data.TrimPattern; import org.geysermc.geyser.GeyserImpl; @@ -42,6 +44,7 @@ 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.MinecraftProtocol; import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; import org.geysermc.mcprotocollib.protocol.packet.configuration.clientbound.ClientboundRegistryDataPacket; @@ -63,6 +66,7 @@ import java.util.function.ToIntFunction; @Accessors(fluent = true) @Getter public final class RegistryCache { + private static final Map> DEFAULTS; private static final Map>> REGISTRIES = new HashMap<>(); static { @@ -73,6 +77,24 @@ public final class RegistryCache { 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())); + + // Load from MCProtocolLib's classloader + NbtMap tag = MinecraftProtocol.loadNetworkCodec(); + Map> defaults = new HashMap<>(); + // Don't create a keySet - no need to create the cached object in HashMap if we don't use it again + REGISTRIES.forEach((key, $) -> { + List rawValues = tag.getCompound(key) + .getList("value", NbtType.COMPOUND); + Map values = new HashMap<>(); + for (NbtMap value : rawValues) { + String name = value.getString("name"); + values.put(name, value.getCompound("element")); + } + // Can make these maps immutable and as efficient as possible after initialization + defaults.put(key, Map.copyOf(values)); + }); + + DEFAULTS = Map.copyOf(defaults); } @Getter(AccessLevel.NONE) @@ -116,13 +138,22 @@ public final class RegistryCache { * @param the class that represents these entries. */ private static void register(String registry, Function> localCacheFunction, BiFunction reader) { - REGISTRIES.put("minecraft:" + registry, (registryCache, entries) -> { + String key = "minecraft:" + registry; + REGISTRIES.put(key, (registryCache, entries) -> { + Map localRegistry = null; JavaRegistry localCache = localCacheFunction.apply(registryCache); // Clear each local cache every time a new registry entry is given to us // (e.g. proxy server switches) List builder = new ArrayList<>(entries.size()); for (int i = 0; i < entries.size(); i++) { RegistryEntry entry = entries.get(i); + // If the data is null, that's the server telling us we need to use our default values. + if (entry.getData() == null) { + if (localRegistry == null) { // Lazy initialize + localRegistry = DEFAULTS.get(key); + } + entry = new RegistryEntry(entry.getId(), localRegistry.get(entry.getId())); + } // This is what Geyser wants to keep as a value for this registry. T cacheEntry = reader.apply(registryCache.session, entry); builder.add(i, cacheEntry); @@ -156,4 +187,8 @@ public final class RegistryCache { localCacheFunction.accept(registryCache, array); }); } + + public static void init() { + // no-op + } } From 9bca012194211b34583e1688bc9e925e138c77f1 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Wed, 15 May 2024 15:31:02 -0400 Subject: [PATCH 008/233] Bump Erosion --- bootstrap/spigot/build.gradle.kts | 6 +++++ .../manager/GeyserSpigotWorldManager.java | 17 ++++++------ .../java/org/geysermc/geyser/GeyserImpl.java | 6 ++++- .../erosion/GeyserboundPacketHandlerImpl.java | 16 +++--------- .../geyser/level/GeyserWorldManager.java | 5 ++-- .../geysermc/geyser/level/WorldManager.java | 26 +++++++++++++++++++ .../protocol/java/JavaLoginTranslator.java | 4 +++ gradle/libs.versions.toml | 7 ++--- 8 files changed, 61 insertions(+), 26 deletions(-) diff --git a/bootstrap/spigot/build.gradle.kts b/bootstrap/spigot/build.gradle.kts index 8143d96a1..7ccb50484 100644 --- a/bootstrap/spigot/build.gradle.kts +++ b/bootstrap/spigot/build.gradle.kts @@ -4,6 +4,12 @@ dependencies { isTransitive = false } + implementation(libs.erosion.bukkit.nms) { + attributes { + attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21) + } + } + implementation(variantOf(libs.adapters.spigot) { classifier("all") // otherwise the unshaded jar is used without the shaded NMS implementations }) 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 8a0e0b70d..47086d36c 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,7 @@ package org.geysermc.geyser.platform.spigot.world.manager; -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 it.unimi.dsi.fastutil.ints.Int2ObjectMap; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.World; @@ -39,6 +37,7 @@ 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; @@ -47,6 +46,9 @@ 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.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.Objects; @@ -205,17 +207,16 @@ public class GeyserSpigotWorldManager extends WorldManager { @Override 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); - return future; + return CompletableFuture.completedFuture(null); } + CompletableFuture> future = new CompletableFuture<>(); 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)*/ null), block); // TODO fix erosion once clear how to handle this - return future; + SchedulerUtils.runTask(this.plugin, () -> future.complete(PickBlockUtils.pickBlock(block)), block); + return future.thenApply(RAW_TRANSFORMER); } /** diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index d5635acf9..a60a14ea0 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -45,6 +45,7 @@ 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; @@ -77,6 +78,7 @@ import org.geysermc.geyser.scoreboard.ScoreboardUpdater; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.PendingMicrosoftAuthentication; import org.geysermc.geyser.session.SessionManager; +import org.geysermc.geyser.session.cache.RegistryCache; import org.geysermc.geyser.skin.FloodgateSkinUploader; import org.geysermc.geyser.skin.ProvidedSkins; import org.geysermc.geyser.skin.SkinProvider; @@ -211,6 +213,8 @@ public class GeyserImpl implements GeyserApi { Registries.init(); BlockRegistries.init(); + RegistryCache.init(); + /* Initialize translators */ EntityDefinitions.init(); MessageTranslator.init(); @@ -383,7 +387,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/erosion/GeyserboundPacketHandlerImpl.java b/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java index a62f9ec49..7d5bba1e8 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,6 @@ package org.geysermc.geyser.erosion; -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; @@ -43,14 +41,7 @@ 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.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.erosion.packet.geyserbound.*; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.physics.Direction; import org.geysermc.geyser.network.GameProtocol; @@ -58,6 +49,7 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.PistonCache; import org.geysermc.geyser.translator.level.block.entity.PistonBlockEntity; import org.geysermc.geyser.util.BlockEntityUtils; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicInteger; @@ -71,7 +63,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); @@ -147,7 +139,7 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke @Override public void handlePickBlock(GeyserboundPickBlockPacket packet) { if (this.pickBlockLookup != null) { - //this.pickBlockLookup.complete(packet.getTag()); // TODO 1.20.5 + this.pickBlockLookup.complete(packet.getComponents()); } } 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 08611a5e1..3144f0cb2 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 it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; @@ -179,9 +180,9 @@ public class GeyserWorldManager extends WorldManager { if (erosionHandler == null) { 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; + return future.thenApply(RAW_TRANSFORMER); } } 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 a1b16a1d5..cd6c9e824 100644 --- a/core/src/main/java/org/geysermc/geyser/level/WorldManager.java +++ b/core/src/main/java/org/geysermc/geyser/level/WorldManager.java @@ -25,19 +25,29 @@ package org.geysermc.geyser.level; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; 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.DataComponent; +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.ItemCodecHelper; import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityInfo; import org.geysermc.mcprotocollib.protocol.data.game.setting.Difficulty; +import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.concurrent.CompletableFuture; +import java.util.function.Function; /** * Class that manages or retrieves various information @@ -223,4 +233,20 @@ public abstract class WorldManager { public CompletableFuture<@Nullable DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addExtraData) { return CompletableFuture.completedFuture(null); } + + protected static final Function, DataComponents> RAW_TRANSFORMER = map -> { + try { + Map, DataComponent> components = new HashMap<>(); + Int2ObjectMaps.fastForEach(map, entry -> { + DataComponentType type = DataComponentType.from(entry.getIntKey()); + ByteBuf buf = Unpooled.wrappedBuffer(entry.getValue()); + DataComponent value = type.readDataComponent(ItemCodecHelper.INSTANCE, buf); + components.put(type, value); + }); + return new DataComponents(components); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + }; } 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 fe4401dca..33d5a88b9 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,6 +25,7 @@ package org.geysermc.geyser.translator.protocol.java; +import org.geysermc.erosion.Constants; 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; @@ -45,6 +46,8 @@ import org.geysermc.geyser.util.ChunkUtils; import org.geysermc.geyser.util.DimensionUtils; import org.geysermc.geyser.util.EntityUtils; +import java.nio.charset.StandardCharsets; + @Translator(packet = ClientboundLoginPacket.class) public class JavaLoginTranslator extends PacketTranslator { @@ -134,6 +137,7 @@ public class JavaLoginTranslator extends PacketTranslator Date: Thu, 16 May 2024 23:12:06 -0400 Subject: [PATCH 009/233] Block refactory --- .../world/GeyserSpigotBlockPlaceListener.java | 3 +- .../GeyserSpigotNativeWorldManager.java | 3 +- .../manager/GeyserSpigotWorldManager.java | 8 +- .../java/org/geysermc/geyser/GeyserImpl.java | 13 + .../geyser/entity/type/FishingHookEntity.java | 3 +- .../erosion/GeyserboundPacketHandlerImpl.java | 3 +- .../geyser/level/block/BlockStateValues.java | 21 +- .../geysermc/geyser/level/block/Blocks.java | 2820 +++++++++++++++++ .../level/block/property/ChestType.java | 34 + .../level/block/property/Properties.java | 146 + .../geyser/level/block/property/Property.java | 43 + .../geyser/level/block/type/BannerBlock.java | 39 + .../geyser/level/block/type/BedBlock.java | 39 + .../geyser/level/block/type/Block.java | 152 + .../geyser/level/block/type/BlockState.java | 64 + .../geyser/registry/BlockRegistries.java | 12 +- .../geyser/registry/ListRegistry.java | 103 + .../populator/BlockRegistryPopulator.java | 2 - .../geyser/session/GeyserSession.java | 3 - .../geyser/session/cache/ChunkCache.java | 13 +- .../inventory/ShulkerInventoryTranslator.java | 3 +- .../chest/DoubleChestInventoryTranslator.java | 7 +- .../entity/BannerBlockEntityTranslator.java | 10 +- .../entity/BeaconBlockEntityTranslator.java | 3 +- .../entity/BedBlockEntityTranslator.java | 12 +- .../block/entity/BedrockOnlyBlockEntity.java | 3 +- .../block/entity/BlockEntityTranslator.java | 5 +- .../BrushableBlockEntityTranslator.java | 7 +- .../entity/CampfireBlockEntityTranslator.java | 3 +- .../CommandBlockBlockEntityTranslator.java | 7 +- .../DecoratedPotBlockEntityTranslator.java | 3 +- .../DoubleChestBlockEntityTranslator.java | 46 +- .../entity/EmptyBlockEntityTranslator.java | 3 +- .../EndGatewayBlockEntityTranslator.java | 3 +- .../FlowerPotBlockEntityTranslator.java | 7 +- .../JigsawBlockBlockEntityTranslator.java | 5 +- .../level/block/entity/PistonBlockEntity.java | 15 +- .../ShulkerBoxBlockEntityTranslator.java | 12 +- .../entity/SignBlockEntityTranslator.java | 3 +- .../entity/SkullBlockEntityTranslator.java | 15 +- .../entity/SpawnerBlockEntityTranslator.java | 5 +- .../StructureBlockBlockEntityTranslator.java | 5 +- .../TrialSpawnerBlockEntityTranslator.java | 3 +- .../BedrockBlockPickRequestTranslator.java | 3 +- ...BedrockInventoryTransactionTranslator.java | 3 +- .../player/BedrockActionTranslator.java | 3 +- .../level/JavaBlockEntityDataTranslator.java | 11 +- .../java/level/JavaBlockEventTranslator.java | 3 +- .../java/level/JavaExplodeTranslator.java | 3 +- .../JavaLevelChunkWithLightTranslator.java | 13 +- .../org/geysermc/geyser/util/ChunkUtils.java | 14 +- .../org/geysermc/geyser/util/SoundUtils.java | 3 +- .../geysermc/geyser/util/StatisticsUtils.java | 9 +- gradle/libs.versions.toml | 3 +- 54 files changed, 3620 insertions(+), 157 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/Blocks.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/property/ChestType.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/property/Property.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/type/BannerBlock.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/type/BedBlock.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/type/Block.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java create mode 100644 core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserSpigotBlockPlaceListener.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserSpigotBlockPlaceListener.java index 71aba11f9..b5f4bd4f9 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserSpigotBlockPlaceListener.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserSpigotBlockPlaceListener.java @@ -34,6 +34,7 @@ import org.bukkit.event.Listener; import org.bukkit.event.block.BlockPlaceEvent; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.platform.spigot.world.manager.GeyserSpigotWorldManager; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.session.GeyserSession; @@ -59,7 +60,7 @@ public class GeyserSpigotBlockPlaceListener implements Listener { event.getBlockPlaced().getX(), event.getBlockPlaced().getY(), event.getBlockPlaced().getZ()))); } else { String javaBlockId = event.getBlockPlaced().getBlockData().getAsString(); - placeBlockSoundPacket.setExtraData(session.getBlockMappings().getBedrockBlockId(BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getOrDefault(javaBlockId, BlockStateValues.JAVA_AIR_ID))); + placeBlockSoundPacket.setExtraData(session.getBlockMappings().getBedrockBlockId(BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getOrDefault(javaBlockId, Block.JAVA_AIR_ID))); } placeBlockSoundPacket.setIdentifier(":"); session.sendUpstreamPacket(placeBlockSoundPacket); 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 45e84d254..c99ca4e78 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 @@ -34,6 +34,7 @@ import org.geysermc.geyser.adapters.WorldAdapter; import org.geysermc.geyser.adapters.paper.PaperAdapters; import org.geysermc.geyser.adapters.spigot.SpigotAdapters; import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.session.GeyserSession; public class GeyserSpigotNativeWorldManager extends GeyserSpigotWorldManager { @@ -52,7 +53,7 @@ public class GeyserSpigotNativeWorldManager extends GeyserSpigotWorldManager { public int getBlockAt(GeyserSession session, int x, int y, int z) { Player player = Bukkit.getPlayer(session.getPlayerEntity().getUsername()); if (player == null) { - return BlockStateValues.JAVA_AIR_ID; + return Block.JAVA_AIR_ID; } return adapter.getBlockAt(player.getWorld(), x, y, z); } 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 47086d36c..a04c60126 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 @@ -70,12 +70,12 @@ public class GeyserSpigotWorldManager extends WorldManager { public int getBlockAt(GeyserSession session, int x, int y, int z) { Player bukkitPlayer; if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUsername())) == null) { - return BlockStateValues.JAVA_AIR_ID; + return org.geysermc.geyser.level.block.type.Block.JAVA_AIR_ID; } World world = bukkitPlayer.getWorld(); if (!world.isChunkLoaded(x >> 4, z >> 4)) { // If the chunk isn't loaded, how could we even be here? - return BlockStateValues.JAVA_AIR_ID; + return org.geysermc.geyser.level.block.type.Block.JAVA_AIR_ID; } return getBlockNetworkId(world.getBlockAt(x, y, z)); @@ -86,9 +86,9 @@ public class GeyserSpigotWorldManager extends WorldManager { // Terrible behavior, but this is basically what's always been happening behind the scenes anyway. CompletableFuture blockData = new CompletableFuture<>(); Bukkit.getRegionScheduler().execute(this.plugin, block.getLocation(), () -> blockData.complete(block.getBlockData().getAsString())); - return BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(blockData.join(), BlockStateValues.JAVA_AIR_ID); + return BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(blockData.join(), org.geysermc.geyser.level.block.type.Block.JAVA_AIR_ID); } - return BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(block.getBlockData().getAsString(), BlockStateValues.JAVA_AIR_ID); + return BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(block.getBlockData().getAsString(), org.geysermc.geyser.level.block.type.Block.JAVA_AIR_ID); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index a60a14ea0..4f572ef63 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -69,6 +69,7 @@ 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.level.block.Blocks; import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.network.netty.GeyserServer; import org.geysermc.geyser.registry.BlockRegistries; @@ -256,6 +257,18 @@ public class GeyserImpl implements GeyserApi { } VersionCheckUtils.checkForOutdatedJava(logger); + + Blocks.VAULT.javaId(); + for (int i = 0; i < BlockRegistries.JAVA_BLOCKS.get().length; i++) { + String cleanIdentifier = BlockRegistries.JAVA_BLOCKS.get(i).getCleanJavaIdentifier(); + String newIdentifier = BlockRegistries.BLOCK_STATES.get(i).block().javaIdentifier(); + if (!cleanIdentifier.equals(newIdentifier)) { + System.out.println("Check block " + BlockRegistries.BLOCK_STATES.get(i).block().javaIdentifier()); + break; + } + } + System.out.println(BlockRegistries.JAVA_BLOCKS.get().length); + System.out.println(BlockRegistries.BLOCK_STATES.get().size()); } private void startInstance() { 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 f4c0cea36..26a64bcae 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 @@ -33,6 +33,7 @@ import org.geysermc.erosion.util.BlockPositionIterator; import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.type.player.PlayerEntity; import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.level.physics.BoundingBox; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.collision.BlockCollision; @@ -162,7 +163,7 @@ public class FishingHookEntity extends ThrowableEntity { */ protected boolean isInAir() { int block = session.getGeyser().getWorldManager().getBlockAt(session, position.toInt()); - return block == BlockStateValues.JAVA_AIR_ID; + return block == Block.JAVA_AIR_ID; } @Override 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 7d5bba1e8..b76dc0b85 100644 --- a/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java +++ b/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java @@ -43,6 +43,7 @@ import org.geysermc.erosion.packet.backendbound.BackendboundInitializePacket; import org.geysermc.erosion.packet.backendbound.BackendboundPacket; import org.geysermc.erosion.packet.geyserbound.*; import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.level.physics.Direction; import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.session.GeyserSession; @@ -119,7 +120,7 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke } CompletableFuture future = this.asyncPendingLookups.remove(transactionId); if (future != null) { - future.complete(BlockStateValues.JAVA_AIR_ID); + future.complete(Block.JAVA_AIR_ID); } } 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 52759c709..205486ced 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 @@ -29,6 +29,7 @@ import com.fasterxml.jackson.databind.JsonNode; import it.unimi.dsi.fastutil.ints.*; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.level.physics.Direction; import org.geysermc.geyser.level.physics.PistonBehavior; import org.geysermc.geyser.registry.BlockRegistries; @@ -48,7 +49,6 @@ public final class BlockStateValues { 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<>(); private static final IntSet HORIZONTAL_FACING_JIGSAWS = new IntOpenHashSet(); @@ -110,11 +110,6 @@ public final class BlockStateValues { } } - if (javaId.contains("command_block")) { - COMMAND_BLOCK_VALUES.put(javaBlockState, javaId.contains("conditional=true") ? (byte) 1 : (byte) 0); - return; - } - if (blockData.get("double_chest_position") != null) { boolean isX = (blockData.get("x") != null); boolean isDirectionPositive = ((blockData.get("x") != null && blockData.get("x").asBoolean()) || @@ -277,16 +272,6 @@ public final class BlockStateValues { return ALL_CAULDRONS.contains(state); } - /** - * The block state in Java and Bedrock both contain the conditional bit, however command block block entity tags - * in Bedrock need the conditional information. - * - * @return the list of all command blocks and if they are conditional (1 or 0) - */ - public static Int2ByteMap getCommandBlockValues() { - return COMMAND_BLOCK_VALUES; - } - /** * All double chest values are part of the block state in Java and part of the block entity tag in Bedrock. * This gives the DoubleChestValue that can be calculated into the final tag. @@ -356,7 +341,7 @@ public final class BlockStateValues { * @return Block state for the piston head */ public static int getPistonHead(Direction direction) { - return PISTON_HEADS.getOrDefault(direction, BlockStateValues.JAVA_AIR_ID); + return PISTON_HEADS.getOrDefault(direction, Block.JAVA_AIR_ID); } /** @@ -420,7 +405,7 @@ public final class BlockStateValues { } public static boolean canPistonMoveBlock(int javaId, boolean isPushing) { - if (javaId == JAVA_AIR_ID) { + if (javaId == Block.JAVA_AIR_ID) { return true; } // Pistons can only be moved if they aren't extended diff --git a/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java new file mode 100644 index 000000000..426895269 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java @@ -0,0 +1,2820 @@ +/* + * Copyright (c) 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.level.block; + +import org.geysermc.geyser.level.block.type.BannerBlock; +import org.geysermc.geyser.level.block.type.BedBlock; +import org.geysermc.geyser.level.block.type.Block; +import org.geysermc.geyser.level.physics.Axis; +import org.geysermc.geyser.level.physics.Direction; +import org.geysermc.geyser.registry.BlockRegistries; + +import static org.geysermc.geyser.level.block.property.Properties.*; +import static org.geysermc.geyser.level.block.type.Block.builder; + +@SuppressWarnings("unused") +public final class Blocks { + public static final Block AIR = register(new Block("air", builder())); + public static final Block STONE = register(new Block("stone", builder())); + public static final Block GRANITE = register(new Block("granite", builder())); + public static final Block POLISHED_GRANITE = register(new Block("polished_granite", builder())); + public static final Block DIORITE = register(new Block("diorite", builder())); + public static final Block POLISHED_DIORITE = register(new Block("polished_diorite", builder())); + public static final Block ANDESITE = register(new Block("andesite", builder())); + public static final Block POLISHED_ANDESITE = register(new Block("polished_andesite", builder())); + public static final Block GRASS_BLOCK = register(new Block("grass_block", builder() + .booleanState(SNOWY))); + public static final Block DIRT = register(new Block("dirt", builder())); + public static final Block COARSE_DIRT = register(new Block("coarse_dirt", builder())); + public static final Block PODZOL = register(new Block("podzol", builder() + .booleanState(SNOWY))); + public static final Block COBBLESTONE = register(new Block("cobblestone", builder())); + public static final Block OAK_PLANKS = register(new Block("oak_planks", builder())); + public static final Block SPRUCE_PLANKS = register(new Block("spruce_planks", builder())); + public static final Block BIRCH_PLANKS = register(new Block("birch_planks", builder())); + public static final Block JUNGLE_PLANKS = register(new Block("jungle_planks", builder())); + public static final Block ACACIA_PLANKS = register(new Block("acacia_planks", builder())); + public static final Block CHERRY_PLANKS = register(new Block("cherry_planks", builder())); + public static final Block DARK_OAK_PLANKS = register(new Block("dark_oak_planks", builder())); + public static final Block MANGROVE_PLANKS = register(new Block("mangrove_planks", builder())); + public static final Block BAMBOO_PLANKS = register(new Block("bamboo_planks", builder())); + public static final Block BAMBOO_MOSAIC = register(new Block("bamboo_mosaic", builder())); + public static final Block OAK_SAPLING = register(new Block("oak_sapling", builder() + .intState(STAGE, 0, 1))); + public static final Block SPRUCE_SAPLING = register(new Block("spruce_sapling", builder() + .intState(STAGE, 0, 1))); + public static final Block BIRCH_SAPLING = register(new Block("birch_sapling", builder() + .intState(STAGE, 0, 1))); + public static final Block JUNGLE_SAPLING = register(new Block("jungle_sapling", builder() + .intState(STAGE, 0, 1))); + public static final Block ACACIA_SAPLING = register(new Block("acacia_sapling", builder() + .intState(STAGE, 0, 1))); + public static final Block CHERRY_SAPLING = register(new Block("cherry_sapling", builder() + .intState(STAGE, 0, 1))); + public static final Block DARK_OAK_SAPLING = register(new Block("dark_oak_sapling", builder() + .intState(STAGE, 0, 1))); + public static final Block MANGROVE_PROPAGULE = register(new Block("mangrove_propagule", builder() + .intState(AGE_4, 0, 4) + .booleanState(HANGING) + .intState(STAGE, 0, 1) + .booleanState(WATERLOGGED))); + public static final Block BEDROCK = register(new Block("bedrock", builder())); + public static final Block WATER = register(new Block("water", builder() + .intState(LEVEL, 0, 15))); + public static final Block LAVA = register(new Block("lava", builder() + .intState(LEVEL, 0, 15))); + public static final Block SAND = register(new Block("sand", builder())); + public static final Block SUSPICIOUS_SAND = register(new Block("suspicious_sand", builder() + .intState(DUSTED, 0, 3))); + public static final Block RED_SAND = register(new Block("red_sand", builder())); + public static final Block GRAVEL = register(new Block("gravel", builder())); + public static final Block SUSPICIOUS_GRAVEL = register(new Block("suspicious_gravel", builder() + .intState(DUSTED, 0, 3))); + public static final Block GOLD_ORE = register(new Block("gold_ore", builder())); + public static final Block DEEPSLATE_GOLD_ORE = register(new Block("deepslate_gold_ore", builder())); + public static final Block IRON_ORE = register(new Block("iron_ore", builder())); + public static final Block DEEPSLATE_IRON_ORE = register(new Block("deepslate_iron_ore", builder())); + public static final Block COAL_ORE = register(new Block("coal_ore", builder())); + public static final Block DEEPSLATE_COAL_ORE = register(new Block("deepslate_coal_ore", builder())); + public static final Block NETHER_GOLD_ORE = register(new Block("nether_gold_ore", builder())); + public static final Block OAK_LOG = register(new Block("oak_log", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block SPRUCE_LOG = register(new Block("spruce_log", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block BIRCH_LOG = register(new Block("birch_log", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block JUNGLE_LOG = register(new Block("jungle_log", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block ACACIA_LOG = register(new Block("acacia_log", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block CHERRY_LOG = register(new Block("cherry_log", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block DARK_OAK_LOG = register(new Block("dark_oak_log", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block MANGROVE_LOG = register(new Block("mangrove_log", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block MANGROVE_ROOTS = register(new Block("mangrove_roots", builder() + .booleanState(WATERLOGGED))); + public static final Block MUDDY_MANGROVE_ROOTS = register(new Block("muddy_mangrove_roots", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block BAMBOO_BLOCK = register(new Block("bamboo_block", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block STRIPPED_SPRUCE_LOG = register(new Block("stripped_spruce_log", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block STRIPPED_BIRCH_LOG = register(new Block("stripped_birch_log", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block STRIPPED_JUNGLE_LOG = register(new Block("stripped_jungle_log", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block STRIPPED_ACACIA_LOG = register(new Block("stripped_acacia_log", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block STRIPPED_CHERRY_LOG = register(new Block("stripped_cherry_log", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block STRIPPED_DARK_OAK_LOG = register(new Block("stripped_dark_oak_log", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block STRIPPED_OAK_LOG = register(new Block("stripped_oak_log", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block STRIPPED_MANGROVE_LOG = register(new Block("stripped_mangrove_log", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block STRIPPED_BAMBOO_BLOCK = register(new Block("stripped_bamboo_block", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block OAK_WOOD = register(new Block("oak_wood", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block SPRUCE_WOOD = register(new Block("spruce_wood", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block BIRCH_WOOD = register(new Block("birch_wood", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block JUNGLE_WOOD = register(new Block("jungle_wood", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block ACACIA_WOOD = register(new Block("acacia_wood", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block CHERRY_WOOD = register(new Block("cherry_wood", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block DARK_OAK_WOOD = register(new Block("dark_oak_wood", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block MANGROVE_WOOD = register(new Block("mangrove_wood", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block STRIPPED_OAK_WOOD = register(new Block("stripped_oak_wood", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block STRIPPED_SPRUCE_WOOD = register(new Block("stripped_spruce_wood", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block STRIPPED_BIRCH_WOOD = register(new Block("stripped_birch_wood", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block STRIPPED_JUNGLE_WOOD = register(new Block("stripped_jungle_wood", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block STRIPPED_ACACIA_WOOD = register(new Block("stripped_acacia_wood", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block STRIPPED_CHERRY_WOOD = register(new Block("stripped_cherry_wood", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block STRIPPED_DARK_OAK_WOOD = register(new Block("stripped_dark_oak_wood", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block STRIPPED_MANGROVE_WOOD = register(new Block("stripped_mangrove_wood", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block OAK_LEAVES = register(new Block("oak_leaves", builder() + .intState(DISTANCE, 1, 7) + .booleanState(PERSISTENT) + .booleanState(WATERLOGGED))); + public static final Block SPRUCE_LEAVES = register(new Block("spruce_leaves", builder() + .intState(DISTANCE, 1, 7) + .booleanState(PERSISTENT) + .booleanState(WATERLOGGED))); + public static final Block BIRCH_LEAVES = register(new Block("birch_leaves", builder() + .intState(DISTANCE, 1, 7) + .booleanState(PERSISTENT) + .booleanState(WATERLOGGED))); + public static final Block JUNGLE_LEAVES = register(new Block("jungle_leaves", builder() + .intState(DISTANCE, 1, 7) + .booleanState(PERSISTENT) + .booleanState(WATERLOGGED))); + public static final Block ACACIA_LEAVES = register(new Block("acacia_leaves", builder() + .intState(DISTANCE, 1, 7) + .booleanState(PERSISTENT) + .booleanState(WATERLOGGED))); + public static final Block CHERRY_LEAVES = register(new Block("cherry_leaves", builder() + .intState(DISTANCE, 1, 7) + .booleanState(PERSISTENT) + .booleanState(WATERLOGGED))); + public static final Block DARK_OAK_LEAVES = register(new Block("dark_oak_leaves", builder() + .intState(DISTANCE, 1, 7) + .booleanState(PERSISTENT) + .booleanState(WATERLOGGED))); + public static final Block MANGROVE_LEAVES = register(new Block("mangrove_leaves", builder() + .intState(DISTANCE, 1, 7) + .booleanState(PERSISTENT) + .booleanState(WATERLOGGED))); + public static final Block AZALEA_LEAVES = register(new Block("azalea_leaves", builder() + .intState(DISTANCE, 1, 7) + .booleanState(PERSISTENT) + .booleanState(WATERLOGGED))); + public static final Block FLOWERING_AZALEA_LEAVES = register(new Block("flowering_azalea_leaves", builder() + .intState(DISTANCE, 1, 7) + .booleanState(PERSISTENT) + .booleanState(WATERLOGGED))); + public static final Block SPONGE = register(new Block("sponge", builder())); + public static final Block WET_SPONGE = register(new Block("wet_sponge", builder())); + public static final Block GLASS = register(new Block("glass", builder())); + public static final Block LAPIS_ORE = register(new Block("lapis_ore", builder())); + public static final Block DEEPSLATE_LAPIS_ORE = register(new Block("deepslate_lapis_ore", builder())); + public static final Block LAPIS_BLOCK = register(new Block("lapis_block", builder())); + public static final Block DISPENSER = register(new Block("dispenser", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) + .booleanState(TRIGGERED))); + public static final Block SANDSTONE = register(new Block("sandstone", builder())); + public static final Block CHISELED_SANDSTONE = register(new Block("chiseled_sandstone", builder())); + public static final Block CUT_SANDSTONE = register(new Block("cut_sandstone", builder())); + public static final Block NOTE_BLOCK = register(new Block("note_block", builder() + .enumState(NOTEBLOCK_INSTRUMENT, "harp", "basedrum", "snare", "hat", "bass", "flute", "bell", "guitar", "chime", "xylophone", "iron_xylophone", "cow_bell", "didgeridoo", "bit", "banjo", "pling", "zombie", "skeleton", "creeper", "dragon", "wither_skeleton", "piglin", "custom_head") + .intState(NOTE, 0, 24) + .booleanState(POWERED))); + public static final Block WHITE_BED = register(new BedBlock("white_bed", 0, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(OCCUPIED) + .enumState(BED_PART, "head", "foot"))); + public static final Block ORANGE_BED = register(new BedBlock("orange_bed", 1, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(OCCUPIED) + .enumState(BED_PART, "head", "foot"))); + public static final Block MAGENTA_BED = register(new BedBlock("magenta_bed", 2, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(OCCUPIED) + .enumState(BED_PART, "head", "foot"))); + public static final Block LIGHT_BLUE_BED = register(new BedBlock("light_blue_bed", 3, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(OCCUPIED) + .enumState(BED_PART, "head", "foot"))); + public static final Block YELLOW_BED = register(new BedBlock("yellow_bed", 4, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(OCCUPIED) + .enumState(BED_PART, "head", "foot"))); + public static final Block LIME_BED = register(new BedBlock("lime_bed", 5, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(OCCUPIED) + .enumState(BED_PART, "head", "foot"))); + public static final Block PINK_BED = register(new BedBlock("pink_bed", 6, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(OCCUPIED) + .enumState(BED_PART, "head", "foot"))); + public static final Block GRAY_BED = register(new BedBlock("gray_bed", 7, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(OCCUPIED) + .enumState(BED_PART, "head", "foot"))); + public static final Block LIGHT_GRAY_BED = register(new BedBlock("light_gray_bed", 8, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(OCCUPIED) + .enumState(BED_PART, "head", "foot"))); + public static final Block CYAN_BED = register(new BedBlock("cyan_bed", 9, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(OCCUPIED) + .enumState(BED_PART, "head", "foot"))); + public static final Block PURPLE_BED = register(new BedBlock("purple_bed", 10, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(OCCUPIED) + .enumState(BED_PART, "head", "foot"))); + public static final Block BLUE_BED = register(new BedBlock("blue_bed", 11, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(OCCUPIED) + .enumState(BED_PART, "head", "foot"))); + public static final Block BROWN_BED = register(new BedBlock("brown_bed", 12, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(OCCUPIED) + .enumState(BED_PART, "head", "foot"))); + public static final Block GREEN_BED = register(new BedBlock("green_bed", 13, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(OCCUPIED) + .enumState(BED_PART, "head", "foot"))); + public static final Block RED_BED = register(new BedBlock("red_bed", 14, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(OCCUPIED) + .enumState(BED_PART, "head", "foot"))); + public static final Block BLACK_BED = register(new BedBlock("black_bed", 15, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(OCCUPIED) + .enumState(BED_PART, "head", "foot"))); + public static final Block POWERED_RAIL = register(new Block("powered_rail", builder() + .booleanState(POWERED) + .enumState(RAIL_SHAPE_STRAIGHT, "north_south", "east_west", "ascending_east", "ascending_west", "ascending_north", "ascending_south") + .booleanState(WATERLOGGED))); + public static final Block DETECTOR_RAIL = register(new Block("detector_rail", builder() + .booleanState(POWERED) + .enumState(RAIL_SHAPE_STRAIGHT, "north_south", "east_west", "ascending_east", "ascending_west", "ascending_north", "ascending_south") + .booleanState(WATERLOGGED))); + public static final Block STICKY_PISTON = register(new Block("sticky_piston", builder() + .booleanState(EXTENDED) + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); + public static final Block COBWEB = register(new Block("cobweb", builder())); + public static final Block SHORT_GRASS = register(new Block("short_grass", builder())); + public static final Block FERN = register(new Block("fern", builder())); + public static final Block DEAD_BUSH = register(new Block("dead_bush", builder())); + public static final Block SEAGRASS = register(new Block("seagrass", builder())); + public static final Block TALL_SEAGRASS = register(new Block("tall_seagrass", builder() + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); + public static final Block PISTON = register(new Block("piston", builder() + .booleanState(EXTENDED) + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); + public static final Block PISTON_HEAD = register(new Block("piston_head", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) + .booleanState(SHORT) + .enumState(PISTON_TYPE, "normal", "sticky"))); + public static final Block WHITE_WOOL = register(new Block("white_wool", builder())); + public static final Block ORANGE_WOOL = register(new Block("orange_wool", builder())); + public static final Block MAGENTA_WOOL = register(new Block("magenta_wool", builder())); + public static final Block LIGHT_BLUE_WOOL = register(new Block("light_blue_wool", builder())); + public static final Block YELLOW_WOOL = register(new Block("yellow_wool", builder())); + public static final Block LIME_WOOL = register(new Block("lime_wool", builder())); + public static final Block PINK_WOOL = register(new Block("pink_wool", builder())); + public static final Block GRAY_WOOL = register(new Block("gray_wool", builder())); + public static final Block LIGHT_GRAY_WOOL = register(new Block("light_gray_wool", builder())); + public static final Block CYAN_WOOL = register(new Block("cyan_wool", builder())); + public static final Block PURPLE_WOOL = register(new Block("purple_wool", builder())); + public static final Block BLUE_WOOL = register(new Block("blue_wool", builder())); + public static final Block BROWN_WOOL = register(new Block("brown_wool", builder())); + public static final Block GREEN_WOOL = register(new Block("green_wool", builder())); + public static final Block RED_WOOL = register(new Block("red_wool", builder())); + public static final Block BLACK_WOOL = register(new Block("black_wool", builder())); + public static final Block MOVING_PISTON = register(new Block("moving_piston", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) + .enumState(PISTON_TYPE, "normal", "sticky"))); + public static final Block DANDELION = register(new Block("dandelion", builder())); + public static final Block TORCHFLOWER = register(new Block("torchflower", builder())); + public static final Block POPPY = register(new Block("poppy", builder())); + public static final Block BLUE_ORCHID = register(new Block("blue_orchid", builder())); + public static final Block ALLIUM = register(new Block("allium", builder())); + public static final Block AZURE_BLUET = register(new Block("azure_bluet", builder())); + public static final Block RED_TULIP = register(new Block("red_tulip", builder())); + public static final Block ORANGE_TULIP = register(new Block("orange_tulip", builder())); + public static final Block WHITE_TULIP = register(new Block("white_tulip", builder())); + public static final Block PINK_TULIP = register(new Block("pink_tulip", builder())); + public static final Block OXEYE_DAISY = register(new Block("oxeye_daisy", builder())); + public static final Block CORNFLOWER = register(new Block("cornflower", builder())); + public static final Block WITHER_ROSE = register(new Block("wither_rose", builder())); + public static final Block LILY_OF_THE_VALLEY = register(new Block("lily_of_the_valley", builder())); + public static final Block BROWN_MUSHROOM = register(new Block("brown_mushroom", builder())); + public static final Block RED_MUSHROOM = register(new Block("red_mushroom", builder())); + public static final Block GOLD_BLOCK = register(new Block("gold_block", builder())); + public static final Block IRON_BLOCK = register(new Block("iron_block", builder())); + public static final Block BRICKS = register(new Block("bricks", builder())); + public static final Block TNT = register(new Block("tnt", builder() + .booleanState(UNSTABLE))); + public static final Block BOOKSHELF = register(new Block("bookshelf", builder())); + public static final Block CHISELED_BOOKSHELF = register(new Block("chiseled_bookshelf", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(CHISELED_BOOKSHELF_SLOT_0_OCCUPIED) + .booleanState(CHISELED_BOOKSHELF_SLOT_1_OCCUPIED) + .booleanState(CHISELED_BOOKSHELF_SLOT_2_OCCUPIED) + .booleanState(CHISELED_BOOKSHELF_SLOT_3_OCCUPIED) + .booleanState(CHISELED_BOOKSHELF_SLOT_4_OCCUPIED) + .booleanState(CHISELED_BOOKSHELF_SLOT_5_OCCUPIED))); + public static final Block MOSSY_COBBLESTONE = register(new Block("mossy_cobblestone", builder())); + public static final Block OBSIDIAN = register(new Block("obsidian", builder())); + public static final Block TORCH = register(new Block("torch", builder())); + public static final Block WALL_TORCH = register(new Block("wall_torch", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block FIRE = register(new Block("fire", builder() + .intState(AGE_15, 0, 15) + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(UP) + .booleanState(WEST))); + public static final Block SOUL_FIRE = register(new Block("soul_fire", builder())); + public static final Block SPAWNER = register(new Block("spawner", builder())); + public static final Block OAK_STAIRS = register(new Block("oak_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block CHEST = register(new Block("chest", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(CHEST_TYPE, "single", "left", "right") + .booleanState(WATERLOGGED))); + public static final Block REDSTONE_WIRE = register(new Block("redstone_wire", builder() + .enumState(EAST_REDSTONE, "up", "side", "none") + .enumState(NORTH_REDSTONE, "up", "side", "none") + .intState(POWER, 0, 15) + .enumState(SOUTH_REDSTONE, "up", "side", "none") + .enumState(WEST_REDSTONE, "up", "side", "none"))); + public static final Block DIAMOND_ORE = register(new Block("diamond_ore", builder())); + public static final Block DEEPSLATE_DIAMOND_ORE = register(new Block("deepslate_diamond_ore", builder())); + public static final Block DIAMOND_BLOCK = register(new Block("diamond_block", builder())); + public static final Block CRAFTING_TABLE = register(new Block("crafting_table", builder())); + public static final Block WHEAT = register(new Block("wheat", builder() + .intState(AGE_7, 0, 7))); + public static final Block FARMLAND = register(new Block("farmland", builder() + .intState(MOISTURE, 0, 7))); + public static final Block FURNACE = register(new Block("furnace", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(LIT))); + public static final Block OAK_SIGN = register(new Block("oak_sign", builder() + .intState(ROTATION_16, 0, 15) + .booleanState(WATERLOGGED))); + public static final Block SPRUCE_SIGN = register(new Block("spruce_sign", builder() + .intState(ROTATION_16, 0, 15) + .booleanState(WATERLOGGED))); + public static final Block BIRCH_SIGN = register(new Block("birch_sign", builder() + .intState(ROTATION_16, 0, 15) + .booleanState(WATERLOGGED))); + public static final Block ACACIA_SIGN = register(new Block("acacia_sign", builder() + .intState(ROTATION_16, 0, 15) + .booleanState(WATERLOGGED))); + public static final Block CHERRY_SIGN = register(new Block("cherry_sign", builder() + .intState(ROTATION_16, 0, 15) + .booleanState(WATERLOGGED))); + public static final Block JUNGLE_SIGN = register(new Block("jungle_sign", builder() + .intState(ROTATION_16, 0, 15) + .booleanState(WATERLOGGED))); + public static final Block DARK_OAK_SIGN = register(new Block("dark_oak_sign", builder() + .intState(ROTATION_16, 0, 15) + .booleanState(WATERLOGGED))); + public static final Block MANGROVE_SIGN = register(new Block("mangrove_sign", builder() + .intState(ROTATION_16, 0, 15) + .booleanState(WATERLOGGED))); + public static final Block BAMBOO_SIGN = register(new Block("bamboo_sign", builder() + .intState(ROTATION_16, 0, 15) + .booleanState(WATERLOGGED))); + public static final Block OAK_DOOR = register(new Block("oak_door", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") + .enumState(DOOR_HINGE, "left", "right") + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block LADDER = register(new Block("ladder", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block RAIL = register(new Block("rail", builder() + .enumState(RAIL_SHAPE, "north_south", "east_west", "ascending_east", "ascending_west", "ascending_north", "ascending_south", "south_east", "south_west", "north_west", "north_east") + .booleanState(WATERLOGGED))); + public static final Block COBBLESTONE_STAIRS = register(new Block("cobblestone_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block OAK_WALL_SIGN = register(new Block("oak_wall_sign", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block SPRUCE_WALL_SIGN = register(new Block("spruce_wall_sign", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block BIRCH_WALL_SIGN = register(new Block("birch_wall_sign", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block ACACIA_WALL_SIGN = register(new Block("acacia_wall_sign", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block CHERRY_WALL_SIGN = register(new Block("cherry_wall_sign", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block JUNGLE_WALL_SIGN = register(new Block("jungle_wall_sign", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block DARK_OAK_WALL_SIGN = register(new Block("dark_oak_wall_sign", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block MANGROVE_WALL_SIGN = register(new Block("mangrove_wall_sign", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block BAMBOO_WALL_SIGN = register(new Block("bamboo_wall_sign", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block OAK_HANGING_SIGN = register(new Block("oak_hanging_sign", builder() + .booleanState(ATTACHED) + .intState(ROTATION_16, 0, 15) + .booleanState(WATERLOGGED))); + public static final Block SPRUCE_HANGING_SIGN = register(new Block("spruce_hanging_sign", builder() + .booleanState(ATTACHED) + .intState(ROTATION_16, 0, 15) + .booleanState(WATERLOGGED))); + public static final Block BIRCH_HANGING_SIGN = register(new Block("birch_hanging_sign", builder() + .booleanState(ATTACHED) + .intState(ROTATION_16, 0, 15) + .booleanState(WATERLOGGED))); + public static final Block ACACIA_HANGING_SIGN = register(new Block("acacia_hanging_sign", builder() + .booleanState(ATTACHED) + .intState(ROTATION_16, 0, 15) + .booleanState(WATERLOGGED))); + public static final Block CHERRY_HANGING_SIGN = register(new Block("cherry_hanging_sign", builder() + .booleanState(ATTACHED) + .intState(ROTATION_16, 0, 15) + .booleanState(WATERLOGGED))); + public static final Block JUNGLE_HANGING_SIGN = register(new Block("jungle_hanging_sign", builder() + .booleanState(ATTACHED) + .intState(ROTATION_16, 0, 15) + .booleanState(WATERLOGGED))); + public static final Block DARK_OAK_HANGING_SIGN = register(new Block("dark_oak_hanging_sign", builder() + .booleanState(ATTACHED) + .intState(ROTATION_16, 0, 15) + .booleanState(WATERLOGGED))); + public static final Block CRIMSON_HANGING_SIGN = register(new Block("crimson_hanging_sign", builder() + .booleanState(ATTACHED) + .intState(ROTATION_16, 0, 15) + .booleanState(WATERLOGGED))); + public static final Block WARPED_HANGING_SIGN = register(new Block("warped_hanging_sign", builder() + .booleanState(ATTACHED) + .intState(ROTATION_16, 0, 15) + .booleanState(WATERLOGGED))); + public static final Block MANGROVE_HANGING_SIGN = register(new Block("mangrove_hanging_sign", builder() + .booleanState(ATTACHED) + .intState(ROTATION_16, 0, 15) + .booleanState(WATERLOGGED))); + public static final Block BAMBOO_HANGING_SIGN = register(new Block("bamboo_hanging_sign", builder() + .booleanState(ATTACHED) + .intState(ROTATION_16, 0, 15) + .booleanState(WATERLOGGED))); + public static final Block OAK_WALL_HANGING_SIGN = register(new Block("oak_wall_hanging_sign", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block SPRUCE_WALL_HANGING_SIGN = register(new Block("spruce_wall_hanging_sign", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block BIRCH_WALL_HANGING_SIGN = register(new Block("birch_wall_hanging_sign", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block ACACIA_WALL_HANGING_SIGN = register(new Block("acacia_wall_hanging_sign", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block CHERRY_WALL_HANGING_SIGN = register(new Block("cherry_wall_hanging_sign", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block JUNGLE_WALL_HANGING_SIGN = register(new Block("jungle_wall_hanging_sign", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block DARK_OAK_WALL_HANGING_SIGN = register(new Block("dark_oak_wall_hanging_sign", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block MANGROVE_WALL_HANGING_SIGN = register(new Block("mangrove_wall_hanging_sign", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block CRIMSON_WALL_HANGING_SIGN = register(new Block("crimson_wall_hanging_sign", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block WARPED_WALL_HANGING_SIGN = register(new Block("warped_wall_hanging_sign", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block BAMBOO_WALL_HANGING_SIGN = register(new Block("bamboo_wall_hanging_sign", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block LEVER = register(new Block("lever", builder() + .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(POWERED))); + public static final Block STONE_PRESSURE_PLATE = register(new Block("stone_pressure_plate", builder() + .booleanState(POWERED))); + public static final Block IRON_DOOR = register(new Block("iron_door", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") + .enumState(DOOR_HINGE, "left", "right") + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block OAK_PRESSURE_PLATE = register(new Block("oak_pressure_plate", builder() + .booleanState(POWERED))); + public static final Block SPRUCE_PRESSURE_PLATE = register(new Block("spruce_pressure_plate", builder() + .booleanState(POWERED))); + public static final Block BIRCH_PRESSURE_PLATE = register(new Block("birch_pressure_plate", builder() + .booleanState(POWERED))); + public static final Block JUNGLE_PRESSURE_PLATE = register(new Block("jungle_pressure_plate", builder() + .booleanState(POWERED))); + public static final Block ACACIA_PRESSURE_PLATE = register(new Block("acacia_pressure_plate", builder() + .booleanState(POWERED))); + public static final Block CHERRY_PRESSURE_PLATE = register(new Block("cherry_pressure_plate", builder() + .booleanState(POWERED))); + public static final Block DARK_OAK_PRESSURE_PLATE = register(new Block("dark_oak_pressure_plate", builder() + .booleanState(POWERED))); + public static final Block MANGROVE_PRESSURE_PLATE = register(new Block("mangrove_pressure_plate", builder() + .booleanState(POWERED))); + public static final Block BAMBOO_PRESSURE_PLATE = register(new Block("bamboo_pressure_plate", builder() + .booleanState(POWERED))); + public static final Block REDSTONE_ORE = register(new Block("redstone_ore", builder() + .booleanState(LIT))); + public static final Block DEEPSLATE_REDSTONE_ORE = register(new Block("deepslate_redstone_ore", builder() + .booleanState(LIT))); + public static final Block REDSTONE_TORCH = register(new Block("redstone_torch", builder() + .booleanState(LIT))); + public static final Block REDSTONE_WALL_TORCH = register(new Block("redstone_wall_torch", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(LIT))); + public static final Block STONE_BUTTON = register(new Block("stone_button", builder() + .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(POWERED))); + public static final Block SNOW = register(new Block("snow", builder() + .intState(LAYERS, 1, 8))); + public static final Block ICE = register(new Block("ice", builder())); + public static final Block SNOW_BLOCK = register(new Block("snow_block", builder())); + public static final Block CACTUS = register(new Block("cactus", builder() + .intState(AGE_15, 0, 15))); + public static final Block CLAY = register(new Block("clay", builder())); + public static final Block SUGAR_CANE = register(new Block("sugar_cane", builder() + .intState(AGE_15, 0, 15))); + public static final Block JUKEBOX = register(new Block("jukebox", builder() + .booleanState(HAS_RECORD))); + public static final Block OAK_FENCE = register(new Block("oak_fence", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block NETHERRACK = register(new Block("netherrack", builder())); + public static final Block SOUL_SAND = register(new Block("soul_sand", builder())); + public static final Block SOUL_SOIL = register(new Block("soul_soil", builder())); + public static final Block BASALT = register(new Block("basalt", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block POLISHED_BASALT = register(new Block("polished_basalt", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block SOUL_TORCH = register(new Block("soul_torch", builder())); + public static final Block SOUL_WALL_TORCH = register(new Block("soul_wall_torch", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block GLOWSTONE = register(new Block("glowstone", builder())); + public static final Block NETHER_PORTAL = register(new Block("nether_portal", builder() + .enumState(HORIZONTAL_AXIS, Axis.X, Axis.Z))); + public static final Block CARVED_PUMPKIN = register(new Block("carved_pumpkin", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block JACK_O_LANTERN = register(new Block("jack_o_lantern", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block CAKE = register(new Block("cake", builder() + .intState(BITES, 0, 6))); + public static final Block REPEATER = register(new Block("repeater", builder() + .intState(DELAY, 1, 4) + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(LOCKED) + .booleanState(POWERED))); + public static final Block WHITE_STAINED_GLASS = register(new Block("white_stained_glass", builder())); + public static final Block ORANGE_STAINED_GLASS = register(new Block("orange_stained_glass", builder())); + public static final Block MAGENTA_STAINED_GLASS = register(new Block("magenta_stained_glass", builder())); + public static final Block LIGHT_BLUE_STAINED_GLASS = register(new Block("light_blue_stained_glass", builder())); + public static final Block YELLOW_STAINED_GLASS = register(new Block("yellow_stained_glass", builder())); + public static final Block LIME_STAINED_GLASS = register(new Block("lime_stained_glass", builder())); + public static final Block PINK_STAINED_GLASS = register(new Block("pink_stained_glass", builder())); + public static final Block GRAY_STAINED_GLASS = register(new Block("gray_stained_glass", builder())); + public static final Block LIGHT_GRAY_STAINED_GLASS = register(new Block("light_gray_stained_glass", builder())); + public static final Block CYAN_STAINED_GLASS = register(new Block("cyan_stained_glass", builder())); + public static final Block PURPLE_STAINED_GLASS = register(new Block("purple_stained_glass", builder())); + public static final Block BLUE_STAINED_GLASS = register(new Block("blue_stained_glass", builder())); + public static final Block BROWN_STAINED_GLASS = register(new Block("brown_stained_glass", builder())); + public static final Block GREEN_STAINED_GLASS = register(new Block("green_stained_glass", builder())); + public static final Block RED_STAINED_GLASS = register(new Block("red_stained_glass", builder())); + public static final Block BLACK_STAINED_GLASS = register(new Block("black_stained_glass", builder())); + public static final Block OAK_TRAPDOOR = register(new Block("oak_trapdoor", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .booleanState(OPEN) + .booleanState(POWERED) + .booleanState(WATERLOGGED))); + public static final Block SPRUCE_TRAPDOOR = register(new Block("spruce_trapdoor", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .booleanState(OPEN) + .booleanState(POWERED) + .booleanState(WATERLOGGED))); + public static final Block BIRCH_TRAPDOOR = register(new Block("birch_trapdoor", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .booleanState(OPEN) + .booleanState(POWERED) + .booleanState(WATERLOGGED))); + public static final Block JUNGLE_TRAPDOOR = register(new Block("jungle_trapdoor", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .booleanState(OPEN) + .booleanState(POWERED) + .booleanState(WATERLOGGED))); + public static final Block ACACIA_TRAPDOOR = register(new Block("acacia_trapdoor", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .booleanState(OPEN) + .booleanState(POWERED) + .booleanState(WATERLOGGED))); + public static final Block CHERRY_TRAPDOOR = register(new Block("cherry_trapdoor", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .booleanState(OPEN) + .booleanState(POWERED) + .booleanState(WATERLOGGED))); + public static final Block DARK_OAK_TRAPDOOR = register(new Block("dark_oak_trapdoor", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .booleanState(OPEN) + .booleanState(POWERED) + .booleanState(WATERLOGGED))); + public static final Block MANGROVE_TRAPDOOR = register(new Block("mangrove_trapdoor", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .booleanState(OPEN) + .booleanState(POWERED) + .booleanState(WATERLOGGED))); + public static final Block BAMBOO_TRAPDOOR = register(new Block("bamboo_trapdoor", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .booleanState(OPEN) + .booleanState(POWERED) + .booleanState(WATERLOGGED))); + public static final Block STONE_BRICKS = register(new Block("stone_bricks", builder())); + public static final Block MOSSY_STONE_BRICKS = register(new Block("mossy_stone_bricks", builder())); + public static final Block CRACKED_STONE_BRICKS = register(new Block("cracked_stone_bricks", builder())); + public static final Block CHISELED_STONE_BRICKS = register(new Block("chiseled_stone_bricks", builder())); + public static final Block PACKED_MUD = register(new Block("packed_mud", builder())); + public static final Block MUD_BRICKS = register(new Block("mud_bricks", builder())); + public static final Block INFESTED_STONE = register(new Block("infested_stone", builder())); + public static final Block INFESTED_COBBLESTONE = register(new Block("infested_cobblestone", builder())); + public static final Block INFESTED_STONE_BRICKS = register(new Block("infested_stone_bricks", builder())); + public static final Block INFESTED_MOSSY_STONE_BRICKS = register(new Block("infested_mossy_stone_bricks", builder())); + public static final Block INFESTED_CRACKED_STONE_BRICKS = register(new Block("infested_cracked_stone_bricks", builder())); + public static final Block INFESTED_CHISELED_STONE_BRICKS = register(new Block("infested_chiseled_stone_bricks", builder())); + public static final Block BROWN_MUSHROOM_BLOCK = register(new Block("brown_mushroom_block", builder() + .booleanState(DOWN) + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(UP) + .booleanState(WEST))); + public static final Block RED_MUSHROOM_BLOCK = register(new Block("red_mushroom_block", builder() + .booleanState(DOWN) + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(UP) + .booleanState(WEST))); + public static final Block MUSHROOM_STEM = register(new Block("mushroom_stem", builder() + .booleanState(DOWN) + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(UP) + .booleanState(WEST))); + public static final Block IRON_BARS = register(new Block("iron_bars", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block CHAIN = register(new Block("chain", builder() + .enumState(AXIS, Axis.VALUES) + .booleanState(WATERLOGGED))); + public static final Block GLASS_PANE = register(new Block("glass_pane", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block PUMPKIN = register(new Block("pumpkin", builder())); + public static final Block MELON = register(new Block("melon", builder())); + public static final Block ATTACHED_PUMPKIN_STEM = register(new Block("attached_pumpkin_stem", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block ATTACHED_MELON_STEM = register(new Block("attached_melon_stem", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block PUMPKIN_STEM = register(new Block("pumpkin_stem", builder() + .intState(AGE_7, 0, 7))); + public static final Block MELON_STEM = register(new Block("melon_stem", builder() + .intState(AGE_7, 0, 7))); + public static final Block VINE = register(new Block("vine", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(UP) + .booleanState(WEST))); + public static final Block GLOW_LICHEN = register(new Block("glow_lichen", builder() + .booleanState(DOWN) + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(UP) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block OAK_FENCE_GATE = register(new Block("oak_fence_gate", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(IN_WALL) + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block BRICK_STAIRS = register(new Block("brick_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block STONE_BRICK_STAIRS = register(new Block("stone_brick_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block MUD_BRICK_STAIRS = register(new Block("mud_brick_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block MYCELIUM = register(new Block("mycelium", builder() + .booleanState(SNOWY))); + public static final Block LILY_PAD = register(new Block("lily_pad", builder())); + public static final Block NETHER_BRICKS = register(new Block("nether_bricks", builder())); + public static final Block NETHER_BRICK_FENCE = register(new Block("nether_brick_fence", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block NETHER_BRICK_STAIRS = register(new Block("nether_brick_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block NETHER_WART = register(new Block("nether_wart", builder() + .intState(AGE_3, 0, 3))); + public static final Block ENCHANTING_TABLE = register(new Block("enchanting_table", builder())); + public static final Block BREWING_STAND = register(new Block("brewing_stand", builder() + .booleanState(HAS_BOTTLE_0) + .booleanState(HAS_BOTTLE_1) + .booleanState(HAS_BOTTLE_2))); + public static final Block CAULDRON = register(new Block("cauldron", builder())); + public static final Block WATER_CAULDRON = register(new Block("water_cauldron", builder() + .intState(LEVEL_CAULDRON, 1, 3))); + public static final Block LAVA_CAULDRON = register(new Block("lava_cauldron", builder())); + public static final Block POWDER_SNOW_CAULDRON = register(new Block("powder_snow_cauldron", builder() + .intState(LEVEL_CAULDRON, 1, 3))); + public static final Block END_PORTAL = register(new Block("end_portal", builder())); + public static final Block END_PORTAL_FRAME = register(new Block("end_portal_frame", builder() + .booleanState(EYE) + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block END_STONE = register(new Block("end_stone", builder())); + public static final Block DRAGON_EGG = register(new Block("dragon_egg", builder())); + public static final Block REDSTONE_LAMP = register(new Block("redstone_lamp", builder() + .booleanState(LIT))); + public static final Block COCOA = register(new Block("cocoa", builder() + .intState(AGE_2, 0, 2) + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block SANDSTONE_STAIRS = register(new Block("sandstone_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block EMERALD_ORE = register(new Block("emerald_ore", builder())); + public static final Block DEEPSLATE_EMERALD_ORE = register(new Block("deepslate_emerald_ore", builder())); + public static final Block ENDER_CHEST = register(new Block("ender_chest", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block TRIPWIRE_HOOK = register(new Block("tripwire_hook", builder() + .booleanState(ATTACHED) + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(POWERED))); + public static final Block TRIPWIRE = register(new Block("tripwire", builder() + .booleanState(ATTACHED) + .booleanState(DISARMED) + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(POWERED) + .booleanState(SOUTH) + .booleanState(WEST))); + public static final Block EMERALD_BLOCK = register(new Block("emerald_block", builder())); + public static final Block SPRUCE_STAIRS = register(new Block("spruce_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block BIRCH_STAIRS = register(new Block("birch_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block JUNGLE_STAIRS = register(new Block("jungle_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block COMMAND_BLOCK = register(new Block("command_block", builder() + .booleanState(CONDITIONAL) + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); + public static final Block BEACON = register(new Block("beacon", builder())); + public static final Block COBBLESTONE_WALL = register(new Block("cobblestone_wall", builder() + .enumState(EAST_WALL, "none", "low", "tall") + .enumState(NORTH_WALL, "none", "low", "tall") + .enumState(SOUTH_WALL, "none", "low", "tall") + .booleanState(UP) + .booleanState(WATERLOGGED) + .enumState(WEST_WALL, "none", "low", "tall"))); + public static final Block MOSSY_COBBLESTONE_WALL = register(new Block("mossy_cobblestone_wall", builder() + .enumState(EAST_WALL, "none", "low", "tall") + .enumState(NORTH_WALL, "none", "low", "tall") + .enumState(SOUTH_WALL, "none", "low", "tall") + .booleanState(UP) + .booleanState(WATERLOGGED) + .enumState(WEST_WALL, "none", "low", "tall"))); + public static final Block FLOWER_POT = register(new Block("flower_pot", builder())); + public static final Block POTTED_TORCHFLOWER = register(new Block("potted_torchflower", builder())); + public static final Block POTTED_OAK_SAPLING = register(new Block("potted_oak_sapling", builder())); + public static final Block POTTED_SPRUCE_SAPLING = register(new Block("potted_spruce_sapling", builder())); + public static final Block POTTED_BIRCH_SAPLING = register(new Block("potted_birch_sapling", builder())); + public static final Block POTTED_JUNGLE_SAPLING = register(new Block("potted_jungle_sapling", builder())); + public static final Block POTTED_ACACIA_SAPLING = register(new Block("potted_acacia_sapling", builder())); + public static final Block POTTED_CHERRY_SAPLING = register(new Block("potted_cherry_sapling", builder())); + public static final Block POTTED_DARK_OAK_SAPLING = register(new Block("potted_dark_oak_sapling", builder())); + public static final Block POTTED_MANGROVE_PROPAGULE = register(new Block("potted_mangrove_propagule", builder())); + public static final Block POTTED_FERN = register(new Block("potted_fern", builder())); + public static final Block POTTED_DANDELION = register(new Block("potted_dandelion", builder())); + public static final Block POTTED_POPPY = register(new Block("potted_poppy", builder())); + public static final Block POTTED_BLUE_ORCHID = register(new Block("potted_blue_orchid", builder())); + public static final Block POTTED_ALLIUM = register(new Block("potted_allium", builder())); + public static final Block POTTED_AZURE_BLUET = register(new Block("potted_azure_bluet", builder())); + public static final Block POTTED_RED_TULIP = register(new Block("potted_red_tulip", builder())); + public static final Block POTTED_ORANGE_TULIP = register(new Block("potted_orange_tulip", builder())); + public static final Block POTTED_WHITE_TULIP = register(new Block("potted_white_tulip", builder())); + public static final Block POTTED_PINK_TULIP = register(new Block("potted_pink_tulip", builder())); + public static final Block POTTED_OXEYE_DAISY = register(new Block("potted_oxeye_daisy", builder())); + public static final Block POTTED_CORNFLOWER = register(new Block("potted_cornflower", builder())); + public static final Block POTTED_LILY_OF_THE_VALLEY = register(new Block("potted_lily_of_the_valley", builder())); + public static final Block POTTED_WITHER_ROSE = register(new Block("potted_wither_rose", builder())); + public static final Block POTTED_RED_MUSHROOM = register(new Block("potted_red_mushroom", builder())); + public static final Block POTTED_BROWN_MUSHROOM = register(new Block("potted_brown_mushroom", builder())); + public static final Block POTTED_DEAD_BUSH = register(new Block("potted_dead_bush", builder())); + public static final Block POTTED_CACTUS = register(new Block("potted_cactus", builder())); + public static final Block CARROTS = register(new Block("carrots", builder() + .intState(AGE_7, 0, 7))); + public static final Block POTATOES = register(new Block("potatoes", builder() + .intState(AGE_7, 0, 7))); + public static final Block OAK_BUTTON = register(new Block("oak_button", builder() + .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(POWERED))); + public static final Block SPRUCE_BUTTON = register(new Block("spruce_button", builder() + .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(POWERED))); + public static final Block BIRCH_BUTTON = register(new Block("birch_button", builder() + .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(POWERED))); + public static final Block JUNGLE_BUTTON = register(new Block("jungle_button", builder() + .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(POWERED))); + public static final Block ACACIA_BUTTON = register(new Block("acacia_button", builder() + .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(POWERED))); + public static final Block CHERRY_BUTTON = register(new Block("cherry_button", builder() + .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(POWERED))); + public static final Block DARK_OAK_BUTTON = register(new Block("dark_oak_button", builder() + .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(POWERED))); + public static final Block MANGROVE_BUTTON = register(new Block("mangrove_button", builder() + .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(POWERED))); + public static final Block BAMBOO_BUTTON = register(new Block("bamboo_button", builder() + .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(POWERED))); + public static final Block SKELETON_SKULL = register(new Block("skeleton_skull", builder() + .booleanState(POWERED) + .intState(ROTATION_16, 0, 15))); + public static final Block SKELETON_WALL_SKULL = register(new Block("skeleton_wall_skull", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(POWERED))); + public static final Block WITHER_SKELETON_SKULL = register(new Block("wither_skeleton_skull", builder() + .booleanState(POWERED) + .intState(ROTATION_16, 0, 15))); + public static final Block WITHER_SKELETON_WALL_SKULL = register(new Block("wither_skeleton_wall_skull", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(POWERED))); + public static final Block ZOMBIE_HEAD = register(new Block("zombie_head", builder() + .booleanState(POWERED) + .intState(ROTATION_16, 0, 15))); + public static final Block ZOMBIE_WALL_HEAD = register(new Block("zombie_wall_head", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(POWERED))); + public static final Block PLAYER_HEAD = register(new Block("player_head", builder() + .booleanState(POWERED) + .intState(ROTATION_16, 0, 15))); + public static final Block PLAYER_WALL_HEAD = register(new Block("player_wall_head", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(POWERED))); + public static final Block CREEPER_HEAD = register(new Block("creeper_head", builder() + .booleanState(POWERED) + .intState(ROTATION_16, 0, 15))); + public static final Block CREEPER_WALL_HEAD = register(new Block("creeper_wall_head", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(POWERED))); + public static final Block DRAGON_HEAD = register(new Block("dragon_head", builder() + .booleanState(POWERED) + .intState(ROTATION_16, 0, 15))); + public static final Block DRAGON_WALL_HEAD = register(new Block("dragon_wall_head", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(POWERED))); + public static final Block PIGLIN_HEAD = register(new Block("piglin_head", builder() + .booleanState(POWERED) + .intState(ROTATION_16, 0, 15))); + public static final Block PIGLIN_WALL_HEAD = register(new Block("piglin_wall_head", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(POWERED))); + public static final Block ANVIL = register(new Block("anvil", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block CHIPPED_ANVIL = register(new Block("chipped_anvil", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block DAMAGED_ANVIL = register(new Block("damaged_anvil", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block TRAPPED_CHEST = register(new Block("trapped_chest", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(CHEST_TYPE, "single", "left", "right") + .booleanState(WATERLOGGED))); + public static final Block LIGHT_WEIGHTED_PRESSURE_PLATE = register(new Block("light_weighted_pressure_plate", builder() + .intState(POWER, 0, 15))); + public static final Block HEAVY_WEIGHTED_PRESSURE_PLATE = register(new Block("heavy_weighted_pressure_plate", builder() + .intState(POWER, 0, 15))); + public static final Block COMPARATOR = register(new Block("comparator", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(MODE_COMPARATOR, "compare", "subtract") + .booleanState(POWERED))); + public static final Block DAYLIGHT_DETECTOR = register(new Block("daylight_detector", builder() + .booleanState(INVERTED) + .intState(POWER, 0, 15))); + public static final Block REDSTONE_BLOCK = register(new Block("redstone_block", builder())); + public static final Block NETHER_QUARTZ_ORE = register(new Block("nether_quartz_ore", builder())); + public static final Block HOPPER = register(new Block("hopper", builder() + .booleanState(ENABLED) + .enumState(FACING_HOPPER, Direction.DOWN, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block QUARTZ_BLOCK = register(new Block("quartz_block", builder())); + public static final Block CHISELED_QUARTZ_BLOCK = register(new Block("chiseled_quartz_block", builder())); + public static final Block QUARTZ_PILLAR = register(new Block("quartz_pillar", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block QUARTZ_STAIRS = register(new Block("quartz_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block ACTIVATOR_RAIL = register(new Block("activator_rail", builder() + .booleanState(POWERED) + .enumState(RAIL_SHAPE_STRAIGHT, "north_south", "east_west", "ascending_east", "ascending_west", "ascending_north", "ascending_south") + .booleanState(WATERLOGGED))); + public static final Block DROPPER = register(new Block("dropper", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) + .booleanState(TRIGGERED))); + public static final Block WHITE_TERRACOTTA = register(new Block("white_terracotta", builder())); + public static final Block ORANGE_TERRACOTTA = register(new Block("orange_terracotta", builder())); + public static final Block MAGENTA_TERRACOTTA = register(new Block("magenta_terracotta", builder())); + public static final Block LIGHT_BLUE_TERRACOTTA = register(new Block("light_blue_terracotta", builder())); + public static final Block YELLOW_TERRACOTTA = register(new Block("yellow_terracotta", builder())); + public static final Block LIME_TERRACOTTA = register(new Block("lime_terracotta", builder())); + public static final Block PINK_TERRACOTTA = register(new Block("pink_terracotta", builder())); + public static final Block GRAY_TERRACOTTA = register(new Block("gray_terracotta", builder())); + public static final Block LIGHT_GRAY_TERRACOTTA = register(new Block("light_gray_terracotta", builder())); + public static final Block CYAN_TERRACOTTA = register(new Block("cyan_terracotta", builder())); + public static final Block PURPLE_TERRACOTTA = register(new Block("purple_terracotta", builder())); + public static final Block BLUE_TERRACOTTA = register(new Block("blue_terracotta", builder())); + public static final Block BROWN_TERRACOTTA = register(new Block("brown_terracotta", builder())); + public static final Block GREEN_TERRACOTTA = register(new Block("green_terracotta", builder())); + public static final Block RED_TERRACOTTA = register(new Block("red_terracotta", builder())); + public static final Block BLACK_TERRACOTTA = register(new Block("black_terracotta", builder())); + public static final Block WHITE_STAINED_GLASS_PANE = register(new Block("white_stained_glass_pane", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block ORANGE_STAINED_GLASS_PANE = register(new Block("orange_stained_glass_pane", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block MAGENTA_STAINED_GLASS_PANE = register(new Block("magenta_stained_glass_pane", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block LIGHT_BLUE_STAINED_GLASS_PANE = register(new Block("light_blue_stained_glass_pane", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block YELLOW_STAINED_GLASS_PANE = register(new Block("yellow_stained_glass_pane", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block LIME_STAINED_GLASS_PANE = register(new Block("lime_stained_glass_pane", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block PINK_STAINED_GLASS_PANE = register(new Block("pink_stained_glass_pane", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block GRAY_STAINED_GLASS_PANE = register(new Block("gray_stained_glass_pane", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block LIGHT_GRAY_STAINED_GLASS_PANE = register(new Block("light_gray_stained_glass_pane", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block CYAN_STAINED_GLASS_PANE = register(new Block("cyan_stained_glass_pane", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block PURPLE_STAINED_GLASS_PANE = register(new Block("purple_stained_glass_pane", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block BLUE_STAINED_GLASS_PANE = register(new Block("blue_stained_glass_pane", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block BROWN_STAINED_GLASS_PANE = register(new Block("brown_stained_glass_pane", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block GREEN_STAINED_GLASS_PANE = register(new Block("green_stained_glass_pane", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block RED_STAINED_GLASS_PANE = register(new Block("red_stained_glass_pane", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block BLACK_STAINED_GLASS_PANE = register(new Block("black_stained_glass_pane", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block ACACIA_STAIRS = register(new Block("acacia_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block CHERRY_STAIRS = register(new Block("cherry_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block DARK_OAK_STAIRS = register(new Block("dark_oak_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block MANGROVE_STAIRS = register(new Block("mangrove_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block BAMBOO_STAIRS = register(new Block("bamboo_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block BAMBOO_MOSAIC_STAIRS = register(new Block("bamboo_mosaic_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block SLIME_BLOCK = register(new Block("slime_block", builder())); + public static final Block BARRIER = register(new Block("barrier", builder() + .booleanState(WATERLOGGED))); + public static final Block LIGHT = register(new Block("light", builder() + .intState(LEVEL, 0, 15) + .booleanState(WATERLOGGED))); + public static final Block IRON_TRAPDOOR = register(new Block("iron_trapdoor", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .booleanState(OPEN) + .booleanState(POWERED) + .booleanState(WATERLOGGED))); + public static final Block PRISMARINE = register(new Block("prismarine", builder())); + public static final Block PRISMARINE_BRICKS = register(new Block("prismarine_bricks", builder())); + public static final Block DARK_PRISMARINE = register(new Block("dark_prismarine", builder())); + public static final Block PRISMARINE_STAIRS = register(new Block("prismarine_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block PRISMARINE_BRICK_STAIRS = register(new Block("prismarine_brick_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block DARK_PRISMARINE_STAIRS = register(new Block("dark_prismarine_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block PRISMARINE_SLAB = register(new Block("prismarine_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block PRISMARINE_BRICK_SLAB = register(new Block("prismarine_brick_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block DARK_PRISMARINE_SLAB = register(new Block("dark_prismarine_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block SEA_LANTERN = register(new Block("sea_lantern", builder())); + public static final Block HAY_BLOCK = register(new Block("hay_block", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block WHITE_CARPET = register(new Block("white_carpet", builder())); + public static final Block ORANGE_CARPET = register(new Block("orange_carpet", builder())); + public static final Block MAGENTA_CARPET = register(new Block("magenta_carpet", builder())); + public static final Block LIGHT_BLUE_CARPET = register(new Block("light_blue_carpet", builder())); + public static final Block YELLOW_CARPET = register(new Block("yellow_carpet", builder())); + public static final Block LIME_CARPET = register(new Block("lime_carpet", builder())); + public static final Block PINK_CARPET = register(new Block("pink_carpet", builder())); + public static final Block GRAY_CARPET = register(new Block("gray_carpet", builder())); + public static final Block LIGHT_GRAY_CARPET = register(new Block("light_gray_carpet", builder())); + public static final Block CYAN_CARPET = register(new Block("cyan_carpet", builder())); + public static final Block PURPLE_CARPET = register(new Block("purple_carpet", builder())); + public static final Block BLUE_CARPET = register(new Block("blue_carpet", builder())); + public static final Block BROWN_CARPET = register(new Block("brown_carpet", builder())); + public static final Block GREEN_CARPET = register(new Block("green_carpet", builder())); + public static final Block RED_CARPET = register(new Block("red_carpet", builder())); + public static final Block BLACK_CARPET = register(new Block("black_carpet", builder())); + public static final Block TERRACOTTA = register(new Block("terracotta", builder())); + public static final Block COAL_BLOCK = register(new Block("coal_block", builder())); + public static final Block PACKED_ICE = register(new Block("packed_ice", builder())); + public static final Block SUNFLOWER = register(new Block("sunflower", builder() + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); + public static final Block LILAC = register(new Block("lilac", builder() + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); + public static final Block ROSE_BUSH = register(new Block("rose_bush", builder() + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); + public static final Block PEONY = register(new Block("peony", builder() + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); + public static final Block TALL_GRASS = register(new Block("tall_grass", builder() + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); + public static final Block LARGE_FERN = register(new Block("large_fern", builder() + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); + public static final Block WHITE_BANNER = register(new BannerBlock("white_banner", 0, builder() + .intState(ROTATION_16, 0, 15))); + public static final Block ORANGE_BANNER = register(new BannerBlock("orange_banner", 1, builder() + .intState(ROTATION_16, 0, 15))); + public static final Block MAGENTA_BANNER = register(new BannerBlock("magenta_banner", 2, builder() + .intState(ROTATION_16, 0, 15))); + public static final Block LIGHT_BLUE_BANNER = register(new BannerBlock("light_blue_banner", 3, builder() + .intState(ROTATION_16, 0, 15))); + public static final Block YELLOW_BANNER = register(new BannerBlock("yellow_banner", 4, builder() + .intState(ROTATION_16, 0, 15))); + public static final Block LIME_BANNER = register(new BannerBlock("lime_banner", 5, builder() + .intState(ROTATION_16, 0, 15))); + public static final Block PINK_BANNER = register(new BannerBlock("pink_banner", 6, builder() + .intState(ROTATION_16, 0, 15))); + public static final Block GRAY_BANNER = register(new BannerBlock("gray_banner", 7, builder() + .intState(ROTATION_16, 0, 15))); + public static final Block LIGHT_GRAY_BANNER = register(new BannerBlock("light_gray_banner", 8, builder() + .intState(ROTATION_16, 0, 15))); + public static final Block CYAN_BANNER = register(new BannerBlock("cyan_banner", 9, builder() + .intState(ROTATION_16, 0, 15))); + public static final Block PURPLE_BANNER = register(new BannerBlock("purple_banner", 10, builder() + .intState(ROTATION_16, 0, 15))); + public static final Block BLUE_BANNER = register(new BannerBlock("blue_banner", 11, builder() + .intState(ROTATION_16, 0, 15))); + public static final Block BROWN_BANNER = register(new BannerBlock("brown_banner", 12, builder() + .intState(ROTATION_16, 0, 15))); + public static final Block GREEN_BANNER = register(new BannerBlock("green_banner", 13, builder() + .intState(ROTATION_16, 0, 15))); + public static final Block RED_BANNER = register(new BannerBlock("red_banner", 14, builder() + .intState(ROTATION_16, 0, 15))); + public static final Block BLACK_BANNER = register(new BannerBlock("black_banner", 15, builder() + .intState(ROTATION_16, 0, 15))); + public static final Block WHITE_WALL_BANNER = register(new BannerBlock("white_wall_banner", 0, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block ORANGE_WALL_BANNER = register(new BannerBlock("orange_wall_banner", 1, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block MAGENTA_WALL_BANNER = register(new BannerBlock("magenta_wall_banner", 2, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block LIGHT_BLUE_WALL_BANNER = register(new BannerBlock("light_blue_wall_banner", 3, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block YELLOW_WALL_BANNER = register(new BannerBlock("yellow_wall_banner", 4, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block LIME_WALL_BANNER = register(new BannerBlock("lime_wall_banner", 5, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block PINK_WALL_BANNER = register(new BannerBlock("pink_wall_banner", 6, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block GRAY_WALL_BANNER = register(new BannerBlock("gray_wall_banner", 7, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block LIGHT_GRAY_WALL_BANNER = register(new BannerBlock("light_gray_wall_banner", 8, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block CYAN_WALL_BANNER = register(new BannerBlock("cyan_wall_banner", 9, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block PURPLE_WALL_BANNER = register(new BannerBlock("purple_wall_banner", 10, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block BLUE_WALL_BANNER = register(new BannerBlock("blue_wall_banner", 11, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block BROWN_WALL_BANNER = register(new BannerBlock("brown_wall_banner", 12, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block GREEN_WALL_BANNER = register(new BannerBlock("green_wall_banner", 13, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block RED_WALL_BANNER = register(new BannerBlock("red_wall_banner", 14, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block BLACK_WALL_BANNER = register(new BannerBlock("black_wall_banner", 15, builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block RED_SANDSTONE = register(new Block("red_sandstone", builder())); + public static final Block CHISELED_RED_SANDSTONE = register(new Block("chiseled_red_sandstone", builder())); + public static final Block CUT_RED_SANDSTONE = register(new Block("cut_red_sandstone", builder())); + public static final Block RED_SANDSTONE_STAIRS = register(new Block("red_sandstone_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block OAK_SLAB = register(new Block("oak_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block SPRUCE_SLAB = register(new Block("spruce_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block BIRCH_SLAB = register(new Block("birch_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block JUNGLE_SLAB = register(new Block("jungle_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block ACACIA_SLAB = register(new Block("acacia_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block CHERRY_SLAB = register(new Block("cherry_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block DARK_OAK_SLAB = register(new Block("dark_oak_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block MANGROVE_SLAB = register(new Block("mangrove_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block BAMBOO_SLAB = register(new Block("bamboo_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block BAMBOO_MOSAIC_SLAB = register(new Block("bamboo_mosaic_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block STONE_SLAB = register(new Block("stone_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block SMOOTH_STONE_SLAB = register(new Block("smooth_stone_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block SANDSTONE_SLAB = register(new Block("sandstone_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block CUT_SANDSTONE_SLAB = register(new Block("cut_sandstone_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block PETRIFIED_OAK_SLAB = register(new Block("petrified_oak_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block COBBLESTONE_SLAB = register(new Block("cobblestone_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block BRICK_SLAB = register(new Block("brick_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block STONE_BRICK_SLAB = register(new Block("stone_brick_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block MUD_BRICK_SLAB = register(new Block("mud_brick_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block NETHER_BRICK_SLAB = register(new Block("nether_brick_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block QUARTZ_SLAB = register(new Block("quartz_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block RED_SANDSTONE_SLAB = register(new Block("red_sandstone_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block CUT_RED_SANDSTONE_SLAB = register(new Block("cut_red_sandstone_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block PURPUR_SLAB = register(new Block("purpur_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block SMOOTH_STONE = register(new Block("smooth_stone", builder())); + public static final Block SMOOTH_SANDSTONE = register(new Block("smooth_sandstone", builder())); + public static final Block SMOOTH_QUARTZ = register(new Block("smooth_quartz", builder())); + public static final Block SMOOTH_RED_SANDSTONE = register(new Block("smooth_red_sandstone", builder())); + public static final Block SPRUCE_FENCE_GATE = register(new Block("spruce_fence_gate", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(IN_WALL) + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block BIRCH_FENCE_GATE = register(new Block("birch_fence_gate", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(IN_WALL) + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block JUNGLE_FENCE_GATE = register(new Block("jungle_fence_gate", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(IN_WALL) + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block ACACIA_FENCE_GATE = register(new Block("acacia_fence_gate", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(IN_WALL) + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block CHERRY_FENCE_GATE = register(new Block("cherry_fence_gate", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(IN_WALL) + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block DARK_OAK_FENCE_GATE = register(new Block("dark_oak_fence_gate", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(IN_WALL) + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block MANGROVE_FENCE_GATE = register(new Block("mangrove_fence_gate", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(IN_WALL) + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block BAMBOO_FENCE_GATE = register(new Block("bamboo_fence_gate", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(IN_WALL) + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block SPRUCE_FENCE = register(new Block("spruce_fence", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block BIRCH_FENCE = register(new Block("birch_fence", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block JUNGLE_FENCE = register(new Block("jungle_fence", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block ACACIA_FENCE = register(new Block("acacia_fence", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block CHERRY_FENCE = register(new Block("cherry_fence", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block DARK_OAK_FENCE = register(new Block("dark_oak_fence", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block MANGROVE_FENCE = register(new Block("mangrove_fence", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block BAMBOO_FENCE = register(new Block("bamboo_fence", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block SPRUCE_DOOR = register(new Block("spruce_door", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") + .enumState(DOOR_HINGE, "left", "right") + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block BIRCH_DOOR = register(new Block("birch_door", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") + .enumState(DOOR_HINGE, "left", "right") + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block JUNGLE_DOOR = register(new Block("jungle_door", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") + .enumState(DOOR_HINGE, "left", "right") + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block ACACIA_DOOR = register(new Block("acacia_door", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") + .enumState(DOOR_HINGE, "left", "right") + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block CHERRY_DOOR = register(new Block("cherry_door", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") + .enumState(DOOR_HINGE, "left", "right") + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block DARK_OAK_DOOR = register(new Block("dark_oak_door", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") + .enumState(DOOR_HINGE, "left", "right") + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block MANGROVE_DOOR = register(new Block("mangrove_door", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") + .enumState(DOOR_HINGE, "left", "right") + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block BAMBOO_DOOR = register(new Block("bamboo_door", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") + .enumState(DOOR_HINGE, "left", "right") + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block END_ROD = register(new Block("end_rod", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); + public static final Block CHORUS_PLANT = register(new Block("chorus_plant", builder() + .booleanState(DOWN) + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(UP) + .booleanState(WEST))); + public static final Block CHORUS_FLOWER = register(new Block("chorus_flower", builder() + .intState(AGE_5, 0, 5))); + public static final Block PURPUR_BLOCK = register(new Block("purpur_block", builder())); + public static final Block PURPUR_PILLAR = register(new Block("purpur_pillar", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block PURPUR_STAIRS = register(new Block("purpur_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block END_STONE_BRICKS = register(new Block("end_stone_bricks", builder())); + public static final Block TORCHFLOWER_CROP = register(new Block("torchflower_crop", builder() + .intState(AGE_1, 0, 1))); + public static final Block PITCHER_CROP = register(new Block("pitcher_crop", builder() + .intState(AGE_4, 0, 4) + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); + public static final Block PITCHER_PLANT = register(new Block("pitcher_plant", builder() + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); + public static final Block BEETROOTS = register(new Block("beetroots", builder() + .intState(AGE_3, 0, 3))); + public static final Block DIRT_PATH = register(new Block("dirt_path", builder())); + public static final Block END_GATEWAY = register(new Block("end_gateway", builder())); + public static final Block REPEATING_COMMAND_BLOCK = register(new Block("repeating_command_block", builder() + .booleanState(CONDITIONAL) + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); + public static final Block CHAIN_COMMAND_BLOCK = register(new Block("chain_command_block", builder() + .booleanState(CONDITIONAL) + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); + public static final Block FROSTED_ICE = register(new Block("frosted_ice", builder() + .intState(AGE_3, 0, 3))); + public static final Block MAGMA_BLOCK = register(new Block("magma_block", builder())); + public static final Block NETHER_WART_BLOCK = register(new Block("nether_wart_block", builder())); + public static final Block RED_NETHER_BRICKS = register(new Block("red_nether_bricks", builder())); + public static final Block BONE_BLOCK = register(new Block("bone_block", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block STRUCTURE_VOID = register(new Block("structure_void", builder())); + public static final Block OBSERVER = register(new Block("observer", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) + .booleanState(POWERED))); + public static final Block SHULKER_BOX = register(new Block("shulker_box", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); + public static final Block WHITE_SHULKER_BOX = register(new Block("white_shulker_box", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); + public static final Block ORANGE_SHULKER_BOX = register(new Block("orange_shulker_box", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); + public static final Block MAGENTA_SHULKER_BOX = register(new Block("magenta_shulker_box", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); + public static final Block LIGHT_BLUE_SHULKER_BOX = register(new Block("light_blue_shulker_box", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); + public static final Block YELLOW_SHULKER_BOX = register(new Block("yellow_shulker_box", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); + public static final Block LIME_SHULKER_BOX = register(new Block("lime_shulker_box", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); + public static final Block PINK_SHULKER_BOX = register(new Block("pink_shulker_box", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); + public static final Block GRAY_SHULKER_BOX = register(new Block("gray_shulker_box", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); + public static final Block LIGHT_GRAY_SHULKER_BOX = register(new Block("light_gray_shulker_box", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); + public static final Block CYAN_SHULKER_BOX = register(new Block("cyan_shulker_box", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); + public static final Block PURPLE_SHULKER_BOX = register(new Block("purple_shulker_box", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); + public static final Block BLUE_SHULKER_BOX = register(new Block("blue_shulker_box", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); + public static final Block BROWN_SHULKER_BOX = register(new Block("brown_shulker_box", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); + public static final Block GREEN_SHULKER_BOX = register(new Block("green_shulker_box", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); + public static final Block RED_SHULKER_BOX = register(new Block("red_shulker_box", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); + public static final Block BLACK_SHULKER_BOX = register(new Block("black_shulker_box", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); + public static final Block WHITE_GLAZED_TERRACOTTA = register(new Block("white_glazed_terracotta", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block ORANGE_GLAZED_TERRACOTTA = register(new Block("orange_glazed_terracotta", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block MAGENTA_GLAZED_TERRACOTTA = register(new Block("magenta_glazed_terracotta", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block LIGHT_BLUE_GLAZED_TERRACOTTA = register(new Block("light_blue_glazed_terracotta", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block YELLOW_GLAZED_TERRACOTTA = register(new Block("yellow_glazed_terracotta", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block LIME_GLAZED_TERRACOTTA = register(new Block("lime_glazed_terracotta", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block PINK_GLAZED_TERRACOTTA = register(new Block("pink_glazed_terracotta", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block GRAY_GLAZED_TERRACOTTA = register(new Block("gray_glazed_terracotta", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block LIGHT_GRAY_GLAZED_TERRACOTTA = register(new Block("light_gray_glazed_terracotta", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block CYAN_GLAZED_TERRACOTTA = register(new Block("cyan_glazed_terracotta", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block PURPLE_GLAZED_TERRACOTTA = register(new Block("purple_glazed_terracotta", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block BLUE_GLAZED_TERRACOTTA = register(new Block("blue_glazed_terracotta", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block BROWN_GLAZED_TERRACOTTA = register(new Block("brown_glazed_terracotta", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block GREEN_GLAZED_TERRACOTTA = register(new Block("green_glazed_terracotta", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block RED_GLAZED_TERRACOTTA = register(new Block("red_glazed_terracotta", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block BLACK_GLAZED_TERRACOTTA = register(new Block("black_glazed_terracotta", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block WHITE_CONCRETE = register(new Block("white_concrete", builder())); + public static final Block ORANGE_CONCRETE = register(new Block("orange_concrete", builder())); + public static final Block MAGENTA_CONCRETE = register(new Block("magenta_concrete", builder())); + public static final Block LIGHT_BLUE_CONCRETE = register(new Block("light_blue_concrete", builder())); + public static final Block YELLOW_CONCRETE = register(new Block("yellow_concrete", builder())); + public static final Block LIME_CONCRETE = register(new Block("lime_concrete", builder())); + public static final Block PINK_CONCRETE = register(new Block("pink_concrete", builder())); + public static final Block GRAY_CONCRETE = register(new Block("gray_concrete", builder())); + public static final Block LIGHT_GRAY_CONCRETE = register(new Block("light_gray_concrete", builder())); + public static final Block CYAN_CONCRETE = register(new Block("cyan_concrete", builder())); + public static final Block PURPLE_CONCRETE = register(new Block("purple_concrete", builder())); + public static final Block BLUE_CONCRETE = register(new Block("blue_concrete", builder())); + public static final Block BROWN_CONCRETE = register(new Block("brown_concrete", builder())); + public static final Block GREEN_CONCRETE = register(new Block("green_concrete", builder())); + public static final Block RED_CONCRETE = register(new Block("red_concrete", builder())); + public static final Block BLACK_CONCRETE = register(new Block("black_concrete", builder())); + public static final Block WHITE_CONCRETE_POWDER = register(new Block("white_concrete_powder", builder())); + public static final Block ORANGE_CONCRETE_POWDER = register(new Block("orange_concrete_powder", builder())); + public static final Block MAGENTA_CONCRETE_POWDER = register(new Block("magenta_concrete_powder", builder())); + public static final Block LIGHT_BLUE_CONCRETE_POWDER = register(new Block("light_blue_concrete_powder", builder())); + public static final Block YELLOW_CONCRETE_POWDER = register(new Block("yellow_concrete_powder", builder())); + public static final Block LIME_CONCRETE_POWDER = register(new Block("lime_concrete_powder", builder())); + public static final Block PINK_CONCRETE_POWDER = register(new Block("pink_concrete_powder", builder())); + public static final Block GRAY_CONCRETE_POWDER = register(new Block("gray_concrete_powder", builder())); + public static final Block LIGHT_GRAY_CONCRETE_POWDER = register(new Block("light_gray_concrete_powder", builder())); + public static final Block CYAN_CONCRETE_POWDER = register(new Block("cyan_concrete_powder", builder())); + public static final Block PURPLE_CONCRETE_POWDER = register(new Block("purple_concrete_powder", builder())); + public static final Block BLUE_CONCRETE_POWDER = register(new Block("blue_concrete_powder", builder())); + public static final Block BROWN_CONCRETE_POWDER = register(new Block("brown_concrete_powder", builder())); + public static final Block GREEN_CONCRETE_POWDER = register(new Block("green_concrete_powder", builder())); + public static final Block RED_CONCRETE_POWDER = register(new Block("red_concrete_powder", builder())); + public static final Block BLACK_CONCRETE_POWDER = register(new Block("black_concrete_powder", builder())); + public static final Block KELP = register(new Block("kelp", builder() + .intState(AGE_25, 0, 25))); + public static final Block KELP_PLANT = register(new Block("kelp_plant", builder())); + public static final Block DRIED_KELP_BLOCK = register(new Block("dried_kelp_block", builder())); + public static final Block TURTLE_EGG = register(new Block("turtle_egg", builder() + .intState(EGGS, 1, 4) + .intState(HATCH, 0, 2))); + public static final Block SNIFFER_EGG = register(new Block("sniffer_egg", builder() + .intState(HATCH, 0, 2))); + public static final Block DEAD_TUBE_CORAL_BLOCK = register(new Block("dead_tube_coral_block", builder())); + public static final Block DEAD_BRAIN_CORAL_BLOCK = register(new Block("dead_brain_coral_block", builder())); + public static final Block DEAD_BUBBLE_CORAL_BLOCK = register(new Block("dead_bubble_coral_block", builder())); + public static final Block DEAD_FIRE_CORAL_BLOCK = register(new Block("dead_fire_coral_block", builder())); + public static final Block DEAD_HORN_CORAL_BLOCK = register(new Block("dead_horn_coral_block", builder())); + public static final Block TUBE_CORAL_BLOCK = register(new Block("tube_coral_block", builder())); + public static final Block BRAIN_CORAL_BLOCK = register(new Block("brain_coral_block", builder())); + public static final Block BUBBLE_CORAL_BLOCK = register(new Block("bubble_coral_block", builder())); + public static final Block FIRE_CORAL_BLOCK = register(new Block("fire_coral_block", builder())); + public static final Block HORN_CORAL_BLOCK = register(new Block("horn_coral_block", builder())); + public static final Block DEAD_TUBE_CORAL = register(new Block("dead_tube_coral", builder() + .booleanState(WATERLOGGED))); + public static final Block DEAD_BRAIN_CORAL = register(new Block("dead_brain_coral", builder() + .booleanState(WATERLOGGED))); + public static final Block DEAD_BUBBLE_CORAL = register(new Block("dead_bubble_coral", builder() + .booleanState(WATERLOGGED))); + public static final Block DEAD_FIRE_CORAL = register(new Block("dead_fire_coral", builder() + .booleanState(WATERLOGGED))); + public static final Block DEAD_HORN_CORAL = register(new Block("dead_horn_coral", builder() + .booleanState(WATERLOGGED))); + public static final Block TUBE_CORAL = register(new Block("tube_coral", builder() + .booleanState(WATERLOGGED))); + public static final Block BRAIN_CORAL = register(new Block("brain_coral", builder() + .booleanState(WATERLOGGED))); + public static final Block BUBBLE_CORAL = register(new Block("bubble_coral", builder() + .booleanState(WATERLOGGED))); + public static final Block FIRE_CORAL = register(new Block("fire_coral", builder() + .booleanState(WATERLOGGED))); + public static final Block HORN_CORAL = register(new Block("horn_coral", builder() + .booleanState(WATERLOGGED))); + public static final Block DEAD_TUBE_CORAL_FAN = register(new Block("dead_tube_coral_fan", builder() + .booleanState(WATERLOGGED))); + public static final Block DEAD_BRAIN_CORAL_FAN = register(new Block("dead_brain_coral_fan", builder() + .booleanState(WATERLOGGED))); + public static final Block DEAD_BUBBLE_CORAL_FAN = register(new Block("dead_bubble_coral_fan", builder() + .booleanState(WATERLOGGED))); + public static final Block DEAD_FIRE_CORAL_FAN = register(new Block("dead_fire_coral_fan", builder() + .booleanState(WATERLOGGED))); + public static final Block DEAD_HORN_CORAL_FAN = register(new Block("dead_horn_coral_fan", builder() + .booleanState(WATERLOGGED))); + public static final Block TUBE_CORAL_FAN = register(new Block("tube_coral_fan", builder() + .booleanState(WATERLOGGED))); + public static final Block BRAIN_CORAL_FAN = register(new Block("brain_coral_fan", builder() + .booleanState(WATERLOGGED))); + public static final Block BUBBLE_CORAL_FAN = register(new Block("bubble_coral_fan", builder() + .booleanState(WATERLOGGED))); + public static final Block FIRE_CORAL_FAN = register(new Block("fire_coral_fan", builder() + .booleanState(WATERLOGGED))); + public static final Block HORN_CORAL_FAN = register(new Block("horn_coral_fan", builder() + .booleanState(WATERLOGGED))); + public static final Block DEAD_TUBE_CORAL_WALL_FAN = register(new Block("dead_tube_coral_wall_fan", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block DEAD_BRAIN_CORAL_WALL_FAN = register(new Block("dead_brain_coral_wall_fan", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block DEAD_BUBBLE_CORAL_WALL_FAN = register(new Block("dead_bubble_coral_wall_fan", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block DEAD_FIRE_CORAL_WALL_FAN = register(new Block("dead_fire_coral_wall_fan", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block DEAD_HORN_CORAL_WALL_FAN = register(new Block("dead_horn_coral_wall_fan", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block TUBE_CORAL_WALL_FAN = register(new Block("tube_coral_wall_fan", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block BRAIN_CORAL_WALL_FAN = register(new Block("brain_coral_wall_fan", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block BUBBLE_CORAL_WALL_FAN = register(new Block("bubble_coral_wall_fan", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block FIRE_CORAL_WALL_FAN = register(new Block("fire_coral_wall_fan", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block HORN_CORAL_WALL_FAN = register(new Block("horn_coral_wall_fan", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block SEA_PICKLE = register(new Block("sea_pickle", builder() + .intState(PICKLES, 1, 4) + .booleanState(WATERLOGGED))); + public static final Block BLUE_ICE = register(new Block("blue_ice", builder())); + public static final Block CONDUIT = register(new Block("conduit", builder() + .booleanState(WATERLOGGED))); + public static final Block BAMBOO_SAPLING = register(new Block("bamboo_sapling", builder())); + public static final Block BAMBOO = register(new Block("bamboo", builder() + .intState(AGE_1, 0, 1) + .enumState(BAMBOO_LEAVES, "none", "small", "large") + .intState(STAGE, 0, 1))); + public static final Block POTTED_BAMBOO = register(new Block("potted_bamboo", builder())); + public static final Block VOID_AIR = register(new Block("void_air", builder())); + public static final Block CAVE_AIR = register(new Block("cave_air", builder())); + public static final Block BUBBLE_COLUMN = register(new Block("bubble_column", builder() + .booleanState(DRAG))); + public static final Block POLISHED_GRANITE_STAIRS = register(new Block("polished_granite_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block SMOOTH_RED_SANDSTONE_STAIRS = register(new Block("smooth_red_sandstone_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block MOSSY_STONE_BRICK_STAIRS = register(new Block("mossy_stone_brick_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block POLISHED_DIORITE_STAIRS = register(new Block("polished_diorite_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block MOSSY_COBBLESTONE_STAIRS = register(new Block("mossy_cobblestone_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block END_STONE_BRICK_STAIRS = register(new Block("end_stone_brick_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block STONE_STAIRS = register(new Block("stone_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block SMOOTH_SANDSTONE_STAIRS = register(new Block("smooth_sandstone_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block SMOOTH_QUARTZ_STAIRS = register(new Block("smooth_quartz_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block GRANITE_STAIRS = register(new Block("granite_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block ANDESITE_STAIRS = register(new Block("andesite_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block RED_NETHER_BRICK_STAIRS = register(new Block("red_nether_brick_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block POLISHED_ANDESITE_STAIRS = register(new Block("polished_andesite_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block DIORITE_STAIRS = register(new Block("diorite_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block POLISHED_GRANITE_SLAB = register(new Block("polished_granite_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block SMOOTH_RED_SANDSTONE_SLAB = register(new Block("smooth_red_sandstone_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block MOSSY_STONE_BRICK_SLAB = register(new Block("mossy_stone_brick_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block POLISHED_DIORITE_SLAB = register(new Block("polished_diorite_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block MOSSY_COBBLESTONE_SLAB = register(new Block("mossy_cobblestone_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block END_STONE_BRICK_SLAB = register(new Block("end_stone_brick_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block SMOOTH_SANDSTONE_SLAB = register(new Block("smooth_sandstone_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block SMOOTH_QUARTZ_SLAB = register(new Block("smooth_quartz_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block GRANITE_SLAB = register(new Block("granite_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block ANDESITE_SLAB = register(new Block("andesite_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block RED_NETHER_BRICK_SLAB = register(new Block("red_nether_brick_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block POLISHED_ANDESITE_SLAB = register(new Block("polished_andesite_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block DIORITE_SLAB = register(new Block("diorite_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block BRICK_WALL = register(new Block("brick_wall", builder() + .enumState(EAST_WALL, "none", "low", "tall") + .enumState(NORTH_WALL, "none", "low", "tall") + .enumState(SOUTH_WALL, "none", "low", "tall") + .booleanState(UP) + .booleanState(WATERLOGGED) + .enumState(WEST_WALL, "none", "low", "tall"))); + public static final Block PRISMARINE_WALL = register(new Block("prismarine_wall", builder() + .enumState(EAST_WALL, "none", "low", "tall") + .enumState(NORTH_WALL, "none", "low", "tall") + .enumState(SOUTH_WALL, "none", "low", "tall") + .booleanState(UP) + .booleanState(WATERLOGGED) + .enumState(WEST_WALL, "none", "low", "tall"))); + public static final Block RED_SANDSTONE_WALL = register(new Block("red_sandstone_wall", builder() + .enumState(EAST_WALL, "none", "low", "tall") + .enumState(NORTH_WALL, "none", "low", "tall") + .enumState(SOUTH_WALL, "none", "low", "tall") + .booleanState(UP) + .booleanState(WATERLOGGED) + .enumState(WEST_WALL, "none", "low", "tall"))); + public static final Block MOSSY_STONE_BRICK_WALL = register(new Block("mossy_stone_brick_wall", builder() + .enumState(EAST_WALL, "none", "low", "tall") + .enumState(NORTH_WALL, "none", "low", "tall") + .enumState(SOUTH_WALL, "none", "low", "tall") + .booleanState(UP) + .booleanState(WATERLOGGED) + .enumState(WEST_WALL, "none", "low", "tall"))); + public static final Block GRANITE_WALL = register(new Block("granite_wall", builder() + .enumState(EAST_WALL, "none", "low", "tall") + .enumState(NORTH_WALL, "none", "low", "tall") + .enumState(SOUTH_WALL, "none", "low", "tall") + .booleanState(UP) + .booleanState(WATERLOGGED) + .enumState(WEST_WALL, "none", "low", "tall"))); + public static final Block STONE_BRICK_WALL = register(new Block("stone_brick_wall", builder() + .enumState(EAST_WALL, "none", "low", "tall") + .enumState(NORTH_WALL, "none", "low", "tall") + .enumState(SOUTH_WALL, "none", "low", "tall") + .booleanState(UP) + .booleanState(WATERLOGGED) + .enumState(WEST_WALL, "none", "low", "tall"))); + public static final Block MUD_BRICK_WALL = register(new Block("mud_brick_wall", builder() + .enumState(EAST_WALL, "none", "low", "tall") + .enumState(NORTH_WALL, "none", "low", "tall") + .enumState(SOUTH_WALL, "none", "low", "tall") + .booleanState(UP) + .booleanState(WATERLOGGED) + .enumState(WEST_WALL, "none", "low", "tall"))); + public static final Block NETHER_BRICK_WALL = register(new Block("nether_brick_wall", builder() + .enumState(EAST_WALL, "none", "low", "tall") + .enumState(NORTH_WALL, "none", "low", "tall") + .enumState(SOUTH_WALL, "none", "low", "tall") + .booleanState(UP) + .booleanState(WATERLOGGED) + .enumState(WEST_WALL, "none", "low", "tall"))); + public static final Block ANDESITE_WALL = register(new Block("andesite_wall", builder() + .enumState(EAST_WALL, "none", "low", "tall") + .enumState(NORTH_WALL, "none", "low", "tall") + .enumState(SOUTH_WALL, "none", "low", "tall") + .booleanState(UP) + .booleanState(WATERLOGGED) + .enumState(WEST_WALL, "none", "low", "tall"))); + public static final Block RED_NETHER_BRICK_WALL = register(new Block("red_nether_brick_wall", builder() + .enumState(EAST_WALL, "none", "low", "tall") + .enumState(NORTH_WALL, "none", "low", "tall") + .enumState(SOUTH_WALL, "none", "low", "tall") + .booleanState(UP) + .booleanState(WATERLOGGED) + .enumState(WEST_WALL, "none", "low", "tall"))); + public static final Block SANDSTONE_WALL = register(new Block("sandstone_wall", builder() + .enumState(EAST_WALL, "none", "low", "tall") + .enumState(NORTH_WALL, "none", "low", "tall") + .enumState(SOUTH_WALL, "none", "low", "tall") + .booleanState(UP) + .booleanState(WATERLOGGED) + .enumState(WEST_WALL, "none", "low", "tall"))); + public static final Block END_STONE_BRICK_WALL = register(new Block("end_stone_brick_wall", builder() + .enumState(EAST_WALL, "none", "low", "tall") + .enumState(NORTH_WALL, "none", "low", "tall") + .enumState(SOUTH_WALL, "none", "low", "tall") + .booleanState(UP) + .booleanState(WATERLOGGED) + .enumState(WEST_WALL, "none", "low", "tall"))); + public static final Block DIORITE_WALL = register(new Block("diorite_wall", builder() + .enumState(EAST_WALL, "none", "low", "tall") + .enumState(NORTH_WALL, "none", "low", "tall") + .enumState(SOUTH_WALL, "none", "low", "tall") + .booleanState(UP) + .booleanState(WATERLOGGED) + .enumState(WEST_WALL, "none", "low", "tall"))); + public static final Block SCAFFOLDING = register(new Block("scaffolding", builder() + .booleanState(BOTTOM) + .intState(STABILITY_DISTANCE, 0, 7) + .booleanState(WATERLOGGED))); + public static final Block LOOM = register(new Block("loom", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block BARREL = register(new Block("barrel", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) + .booleanState(OPEN))); + public static final Block SMOKER = register(new Block("smoker", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(LIT))); + public static final Block BLAST_FURNACE = register(new Block("blast_furnace", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(LIT))); + public static final Block CARTOGRAPHY_TABLE = register(new Block("cartography_table", builder())); + public static final Block FLETCHING_TABLE = register(new Block("fletching_table", builder())); + public static final Block GRINDSTONE = register(new Block("grindstone", builder() + .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block LECTERN = register(new Block("lectern", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(HAS_BOOK) + .booleanState(POWERED))); + public static final Block SMITHING_TABLE = register(new Block("smithing_table", builder())); + public static final Block STONECUTTER = register(new Block("stonecutter", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); + public static final Block BELL = register(new Block("bell", builder() + .enumState(BELL_ATTACHMENT, "floor", "ceiling", "single_wall", "double_wall") + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(POWERED))); + public static final Block LANTERN = register(new Block("lantern", builder() + .booleanState(HANGING) + .booleanState(WATERLOGGED))); + public static final Block SOUL_LANTERN = register(new Block("soul_lantern", builder() + .booleanState(HANGING) + .booleanState(WATERLOGGED))); + public static final Block CAMPFIRE = register(new Block("campfire", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(LIT) + .booleanState(SIGNAL_FIRE) + .booleanState(WATERLOGGED))); + public static final Block SOUL_CAMPFIRE = register(new Block("soul_campfire", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(LIT) + .booleanState(SIGNAL_FIRE) + .booleanState(WATERLOGGED))); + public static final Block SWEET_BERRY_BUSH = register(new Block("sweet_berry_bush", builder() + .intState(AGE_3, 0, 3))); + public static final Block WARPED_STEM = register(new Block("warped_stem", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block STRIPPED_WARPED_STEM = register(new Block("stripped_warped_stem", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block WARPED_HYPHAE = register(new Block("warped_hyphae", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block STRIPPED_WARPED_HYPHAE = register(new Block("stripped_warped_hyphae", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block WARPED_NYLIUM = register(new Block("warped_nylium", builder())); + public static final Block WARPED_FUNGUS = register(new Block("warped_fungus", builder())); + public static final Block WARPED_WART_BLOCK = register(new Block("warped_wart_block", builder())); + public static final Block WARPED_ROOTS = register(new Block("warped_roots", builder())); + public static final Block NETHER_SPROUTS = register(new Block("nether_sprouts", builder())); + public static final Block CRIMSON_STEM = register(new Block("crimson_stem", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block STRIPPED_CRIMSON_STEM = register(new Block("stripped_crimson_stem", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block CRIMSON_HYPHAE = register(new Block("crimson_hyphae", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block STRIPPED_CRIMSON_HYPHAE = register(new Block("stripped_crimson_hyphae", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block CRIMSON_NYLIUM = register(new Block("crimson_nylium", builder())); + public static final Block CRIMSON_FUNGUS = register(new Block("crimson_fungus", builder())); + public static final Block SHROOMLIGHT = register(new Block("shroomlight", builder())); + public static final Block WEEPING_VINES = register(new Block("weeping_vines", builder() + .intState(AGE_25, 0, 25))); + public static final Block WEEPING_VINES_PLANT = register(new Block("weeping_vines_plant", builder())); + public static final Block TWISTING_VINES = register(new Block("twisting_vines", builder() + .intState(AGE_25, 0, 25))); + public static final Block TWISTING_VINES_PLANT = register(new Block("twisting_vines_plant", builder())); + public static final Block CRIMSON_ROOTS = register(new Block("crimson_roots", builder())); + public static final Block CRIMSON_PLANKS = register(new Block("crimson_planks", builder())); + public static final Block WARPED_PLANKS = register(new Block("warped_planks", builder())); + public static final Block CRIMSON_SLAB = register(new Block("crimson_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block WARPED_SLAB = register(new Block("warped_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block CRIMSON_PRESSURE_PLATE = register(new Block("crimson_pressure_plate", builder() + .booleanState(POWERED))); + public static final Block WARPED_PRESSURE_PLATE = register(new Block("warped_pressure_plate", builder() + .booleanState(POWERED))); + public static final Block CRIMSON_FENCE = register(new Block("crimson_fence", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block WARPED_FENCE = register(new Block("warped_fence", builder() + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block CRIMSON_TRAPDOOR = register(new Block("crimson_trapdoor", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .booleanState(OPEN) + .booleanState(POWERED) + .booleanState(WATERLOGGED))); + public static final Block WARPED_TRAPDOOR = register(new Block("warped_trapdoor", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .booleanState(OPEN) + .booleanState(POWERED) + .booleanState(WATERLOGGED))); + public static final Block CRIMSON_FENCE_GATE = register(new Block("crimson_fence_gate", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(IN_WALL) + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block WARPED_FENCE_GATE = register(new Block("warped_fence_gate", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(IN_WALL) + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block CRIMSON_STAIRS = register(new Block("crimson_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block WARPED_STAIRS = register(new Block("warped_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block CRIMSON_BUTTON = register(new Block("crimson_button", builder() + .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(POWERED))); + public static final Block WARPED_BUTTON = register(new Block("warped_button", builder() + .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(POWERED))); + public static final Block CRIMSON_DOOR = register(new Block("crimson_door", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") + .enumState(DOOR_HINGE, "left", "right") + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block WARPED_DOOR = register(new Block("warped_door", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") + .enumState(DOOR_HINGE, "left", "right") + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block CRIMSON_SIGN = register(new Block("crimson_sign", builder() + .intState(ROTATION_16, 0, 15) + .booleanState(WATERLOGGED))); + public static final Block WARPED_SIGN = register(new Block("warped_sign", builder() + .intState(ROTATION_16, 0, 15) + .booleanState(WATERLOGGED))); + public static final Block CRIMSON_WALL_SIGN = register(new Block("crimson_wall_sign", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block WARPED_WALL_SIGN = register(new Block("warped_wall_sign", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block STRUCTURE_BLOCK = register(new Block("structure_block", builder() + .enumState(STRUCTUREBLOCK_MODE, "save", "load", "corner", "data"))); + public static final Block JIGSAW = register(new Block("jigsaw", builder() + .enumState(ORIENTATION, "down_east", "down_north", "down_south", "down_west", "up_east", "up_north", "up_south", "up_west", "west_up", "east_up", "north_up", "south_up"))); + public static final Block COMPOSTER = register(new Block("composter", builder() + .intState(LEVEL_COMPOSTER, 0, 8))); + public static final Block TARGET = register(new Block("target", builder() + .intState(POWER, 0, 15))); + public static final Block BEE_NEST = register(new Block("bee_nest", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .intState(LEVEL_HONEY, 0, 5))); + public static final Block BEEHIVE = register(new Block("beehive", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .intState(LEVEL_HONEY, 0, 5))); + public static final Block HONEY_BLOCK = register(new Block("honey_block", builder())); + public static final Block HONEYCOMB_BLOCK = register(new Block("honeycomb_block", builder())); + public static final Block NETHERITE_BLOCK = register(new Block("netherite_block", builder())); + public static final Block ANCIENT_DEBRIS = register(new Block("ancient_debris", builder())); + public static final Block CRYING_OBSIDIAN = register(new Block("crying_obsidian", builder())); + public static final Block RESPAWN_ANCHOR = register(new Block("respawn_anchor", builder() + .intState(RESPAWN_ANCHOR_CHARGES, 0, 4))); + public static final Block POTTED_CRIMSON_FUNGUS = register(new Block("potted_crimson_fungus", builder())); + public static final Block POTTED_WARPED_FUNGUS = register(new Block("potted_warped_fungus", builder())); + public static final Block POTTED_CRIMSON_ROOTS = register(new Block("potted_crimson_roots", builder())); + public static final Block POTTED_WARPED_ROOTS = register(new Block("potted_warped_roots", builder())); + public static final Block LODESTONE = register(new Block("lodestone", builder())); + public static final Block BLACKSTONE = register(new Block("blackstone", builder())); + public static final Block BLACKSTONE_STAIRS = register(new Block("blackstone_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block BLACKSTONE_WALL = register(new Block("blackstone_wall", builder() + .enumState(EAST_WALL, "none", "low", "tall") + .enumState(NORTH_WALL, "none", "low", "tall") + .enumState(SOUTH_WALL, "none", "low", "tall") + .booleanState(UP) + .booleanState(WATERLOGGED) + .enumState(WEST_WALL, "none", "low", "tall"))); + public static final Block BLACKSTONE_SLAB = register(new Block("blackstone_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block POLISHED_BLACKSTONE = register(new Block("polished_blackstone", builder())); + public static final Block POLISHED_BLACKSTONE_BRICKS = register(new Block("polished_blackstone_bricks", builder())); + public static final Block CRACKED_POLISHED_BLACKSTONE_BRICKS = register(new Block("cracked_polished_blackstone_bricks", builder())); + public static final Block CHISELED_POLISHED_BLACKSTONE = register(new Block("chiseled_polished_blackstone", builder())); + public static final Block POLISHED_BLACKSTONE_BRICK_SLAB = register(new Block("polished_blackstone_brick_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block POLISHED_BLACKSTONE_BRICK_STAIRS = register(new Block("polished_blackstone_brick_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block POLISHED_BLACKSTONE_BRICK_WALL = register(new Block("polished_blackstone_brick_wall", builder() + .enumState(EAST_WALL, "none", "low", "tall") + .enumState(NORTH_WALL, "none", "low", "tall") + .enumState(SOUTH_WALL, "none", "low", "tall") + .booleanState(UP) + .booleanState(WATERLOGGED) + .enumState(WEST_WALL, "none", "low", "tall"))); + public static final Block GILDED_BLACKSTONE = register(new Block("gilded_blackstone", builder())); + public static final Block POLISHED_BLACKSTONE_STAIRS = register(new Block("polished_blackstone_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block POLISHED_BLACKSTONE_SLAB = register(new Block("polished_blackstone_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block POLISHED_BLACKSTONE_PRESSURE_PLATE = register(new Block("polished_blackstone_pressure_plate", builder() + .booleanState(POWERED))); + public static final Block POLISHED_BLACKSTONE_BUTTON = register(new Block("polished_blackstone_button", builder() + .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(POWERED))); + public static final Block POLISHED_BLACKSTONE_WALL = register(new Block("polished_blackstone_wall", builder() + .enumState(EAST_WALL, "none", "low", "tall") + .enumState(NORTH_WALL, "none", "low", "tall") + .enumState(SOUTH_WALL, "none", "low", "tall") + .booleanState(UP) + .booleanState(WATERLOGGED) + .enumState(WEST_WALL, "none", "low", "tall"))); + public static final Block CHISELED_NETHER_BRICKS = register(new Block("chiseled_nether_bricks", builder())); + public static final Block CRACKED_NETHER_BRICKS = register(new Block("cracked_nether_bricks", builder())); + public static final Block QUARTZ_BRICKS = register(new Block("quartz_bricks", builder())); + public static final Block CANDLE = register(new Block("candle", builder() + .intState(CANDLES, 1, 4) + .booleanState(LIT) + .booleanState(WATERLOGGED))); + public static final Block WHITE_CANDLE = register(new Block("white_candle", builder() + .intState(CANDLES, 1, 4) + .booleanState(LIT) + .booleanState(WATERLOGGED))); + public static final Block ORANGE_CANDLE = register(new Block("orange_candle", builder() + .intState(CANDLES, 1, 4) + .booleanState(LIT) + .booleanState(WATERLOGGED))); + public static final Block MAGENTA_CANDLE = register(new Block("magenta_candle", builder() + .intState(CANDLES, 1, 4) + .booleanState(LIT) + .booleanState(WATERLOGGED))); + public static final Block LIGHT_BLUE_CANDLE = register(new Block("light_blue_candle", builder() + .intState(CANDLES, 1, 4) + .booleanState(LIT) + .booleanState(WATERLOGGED))); + public static final Block YELLOW_CANDLE = register(new Block("yellow_candle", builder() + .intState(CANDLES, 1, 4) + .booleanState(LIT) + .booleanState(WATERLOGGED))); + public static final Block LIME_CANDLE = register(new Block("lime_candle", builder() + .intState(CANDLES, 1, 4) + .booleanState(LIT) + .booleanState(WATERLOGGED))); + public static final Block PINK_CANDLE = register(new Block("pink_candle", builder() + .intState(CANDLES, 1, 4) + .booleanState(LIT) + .booleanState(WATERLOGGED))); + public static final Block GRAY_CANDLE = register(new Block("gray_candle", builder() + .intState(CANDLES, 1, 4) + .booleanState(LIT) + .booleanState(WATERLOGGED))); + public static final Block LIGHT_GRAY_CANDLE = register(new Block("light_gray_candle", builder() + .intState(CANDLES, 1, 4) + .booleanState(LIT) + .booleanState(WATERLOGGED))); + public static final Block CYAN_CANDLE = register(new Block("cyan_candle", builder() + .intState(CANDLES, 1, 4) + .booleanState(LIT) + .booleanState(WATERLOGGED))); + public static final Block PURPLE_CANDLE = register(new Block("purple_candle", builder() + .intState(CANDLES, 1, 4) + .booleanState(LIT) + .booleanState(WATERLOGGED))); + public static final Block BLUE_CANDLE = register(new Block("blue_candle", builder() + .intState(CANDLES, 1, 4) + .booleanState(LIT) + .booleanState(WATERLOGGED))); + public static final Block BROWN_CANDLE = register(new Block("brown_candle", builder() + .intState(CANDLES, 1, 4) + .booleanState(LIT) + .booleanState(WATERLOGGED))); + public static final Block GREEN_CANDLE = register(new Block("green_candle", builder() + .intState(CANDLES, 1, 4) + .booleanState(LIT) + .booleanState(WATERLOGGED))); + public static final Block RED_CANDLE = register(new Block("red_candle", builder() + .intState(CANDLES, 1, 4) + .booleanState(LIT) + .booleanState(WATERLOGGED))); + public static final Block BLACK_CANDLE = register(new Block("black_candle", builder() + .intState(CANDLES, 1, 4) + .booleanState(LIT) + .booleanState(WATERLOGGED))); + public static final Block CANDLE_CAKE = register(new Block("candle_cake", builder() + .booleanState(LIT))); + public static final Block WHITE_CANDLE_CAKE = register(new Block("white_candle_cake", builder() + .booleanState(LIT))); + public static final Block ORANGE_CANDLE_CAKE = register(new Block("orange_candle_cake", builder() + .booleanState(LIT))); + public static final Block MAGENTA_CANDLE_CAKE = register(new Block("magenta_candle_cake", builder() + .booleanState(LIT))); + public static final Block LIGHT_BLUE_CANDLE_CAKE = register(new Block("light_blue_candle_cake", builder() + .booleanState(LIT))); + public static final Block YELLOW_CANDLE_CAKE = register(new Block("yellow_candle_cake", builder() + .booleanState(LIT))); + public static final Block LIME_CANDLE_CAKE = register(new Block("lime_candle_cake", builder() + .booleanState(LIT))); + public static final Block PINK_CANDLE_CAKE = register(new Block("pink_candle_cake", builder() + .booleanState(LIT))); + public static final Block GRAY_CANDLE_CAKE = register(new Block("gray_candle_cake", builder() + .booleanState(LIT))); + public static final Block LIGHT_GRAY_CANDLE_CAKE = register(new Block("light_gray_candle_cake", builder() + .booleanState(LIT))); + public static final Block CYAN_CANDLE_CAKE = register(new Block("cyan_candle_cake", builder() + .booleanState(LIT))); + public static final Block PURPLE_CANDLE_CAKE = register(new Block("purple_candle_cake", builder() + .booleanState(LIT))); + public static final Block BLUE_CANDLE_CAKE = register(new Block("blue_candle_cake", builder() + .booleanState(LIT))); + public static final Block BROWN_CANDLE_CAKE = register(new Block("brown_candle_cake", builder() + .booleanState(LIT))); + public static final Block GREEN_CANDLE_CAKE = register(new Block("green_candle_cake", builder() + .booleanState(LIT))); + public static final Block RED_CANDLE_CAKE = register(new Block("red_candle_cake", builder() + .booleanState(LIT))); + public static final Block BLACK_CANDLE_CAKE = register(new Block("black_candle_cake", builder() + .booleanState(LIT))); + public static final Block AMETHYST_BLOCK = register(new Block("amethyst_block", builder())); + public static final Block BUDDING_AMETHYST = register(new Block("budding_amethyst", builder())); + public static final Block AMETHYST_CLUSTER = register(new Block("amethyst_cluster", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) + .booleanState(WATERLOGGED))); + public static final Block LARGE_AMETHYST_BUD = register(new Block("large_amethyst_bud", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) + .booleanState(WATERLOGGED))); + public static final Block MEDIUM_AMETHYST_BUD = register(new Block("medium_amethyst_bud", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) + .booleanState(WATERLOGGED))); + public static final Block SMALL_AMETHYST_BUD = register(new Block("small_amethyst_bud", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) + .booleanState(WATERLOGGED))); + public static final Block TUFF = register(new Block("tuff", builder())); + public static final Block TUFF_SLAB = register(new Block("tuff_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block TUFF_STAIRS = register(new Block("tuff_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block TUFF_WALL = register(new Block("tuff_wall", builder() + .enumState(EAST_WALL, "none", "low", "tall") + .enumState(NORTH_WALL, "none", "low", "tall") + .enumState(SOUTH_WALL, "none", "low", "tall") + .booleanState(UP) + .booleanState(WATERLOGGED) + .enumState(WEST_WALL, "none", "low", "tall"))); + public static final Block POLISHED_TUFF = register(new Block("polished_tuff", builder())); + public static final Block POLISHED_TUFF_SLAB = register(new Block("polished_tuff_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block POLISHED_TUFF_STAIRS = register(new Block("polished_tuff_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block POLISHED_TUFF_WALL = register(new Block("polished_tuff_wall", builder() + .enumState(EAST_WALL, "none", "low", "tall") + .enumState(NORTH_WALL, "none", "low", "tall") + .enumState(SOUTH_WALL, "none", "low", "tall") + .booleanState(UP) + .booleanState(WATERLOGGED) + .enumState(WEST_WALL, "none", "low", "tall"))); + public static final Block CHISELED_TUFF = register(new Block("chiseled_tuff", builder())); + public static final Block TUFF_BRICKS = register(new Block("tuff_bricks", builder())); + public static final Block TUFF_BRICK_SLAB = register(new Block("tuff_brick_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block TUFF_BRICK_STAIRS = register(new Block("tuff_brick_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block TUFF_BRICK_WALL = register(new Block("tuff_brick_wall", builder() + .enumState(EAST_WALL, "none", "low", "tall") + .enumState(NORTH_WALL, "none", "low", "tall") + .enumState(SOUTH_WALL, "none", "low", "tall") + .booleanState(UP) + .booleanState(WATERLOGGED) + .enumState(WEST_WALL, "none", "low", "tall"))); + public static final Block CHISELED_TUFF_BRICKS = register(new Block("chiseled_tuff_bricks", builder())); + public static final Block CALCITE = register(new Block("calcite", builder())); + public static final Block TINTED_GLASS = register(new Block("tinted_glass", builder())); + public static final Block POWDER_SNOW = register(new Block("powder_snow", builder())); + public static final Block SCULK_SENSOR = register(new Block("sculk_sensor", builder() + .intState(POWER, 0, 15) + .enumState(SCULK_SENSOR_PHASE, "inactive", "active", "cooldown") + .booleanState(WATERLOGGED))); + public static final Block CALIBRATED_SCULK_SENSOR = register(new Block("calibrated_sculk_sensor", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .intState(POWER, 0, 15) + .enumState(SCULK_SENSOR_PHASE, "inactive", "active", "cooldown") + .booleanState(WATERLOGGED))); + public static final Block SCULK = register(new Block("sculk", builder())); + public static final Block SCULK_VEIN = register(new Block("sculk_vein", builder() + .booleanState(DOWN) + .booleanState(EAST) + .booleanState(NORTH) + .booleanState(SOUTH) + .booleanState(UP) + .booleanState(WATERLOGGED) + .booleanState(WEST))); + public static final Block SCULK_CATALYST = register(new Block("sculk_catalyst", builder() + .booleanState(BLOOM))); + public static final Block SCULK_SHRIEKER = register(new Block("sculk_shrieker", builder() + .booleanState(CAN_SUMMON) + .booleanState(SHRIEKING) + .booleanState(WATERLOGGED))); + public static final Block COPPER_BLOCK = register(new Block("copper_block", builder())); + public static final Block EXPOSED_COPPER = register(new Block("exposed_copper", builder())); + public static final Block WEATHERED_COPPER = register(new Block("weathered_copper", builder())); + public static final Block OXIDIZED_COPPER = register(new Block("oxidized_copper", builder())); + public static final Block COPPER_ORE = register(new Block("copper_ore", builder())); + public static final Block DEEPSLATE_COPPER_ORE = register(new Block("deepslate_copper_ore", builder())); + public static final Block OXIDIZED_CUT_COPPER = register(new Block("oxidized_cut_copper", builder())); + public static final Block WEATHERED_CUT_COPPER = register(new Block("weathered_cut_copper", builder())); + public static final Block EXPOSED_CUT_COPPER = register(new Block("exposed_cut_copper", builder())); + public static final Block CUT_COPPER = register(new Block("cut_copper", builder())); + public static final Block OXIDIZED_CHISELED_COPPER = register(new Block("oxidized_chiseled_copper", builder())); + public static final Block WEATHERED_CHISELED_COPPER = register(new Block("weathered_chiseled_copper", builder())); + public static final Block EXPOSED_CHISELED_COPPER = register(new Block("exposed_chiseled_copper", builder())); + public static final Block CHISELED_COPPER = register(new Block("chiseled_copper", builder())); + public static final Block WAXED_OXIDIZED_CHISELED_COPPER = register(new Block("waxed_oxidized_chiseled_copper", builder())); + public static final Block WAXED_WEATHERED_CHISELED_COPPER = register(new Block("waxed_weathered_chiseled_copper", builder())); + public static final Block WAXED_EXPOSED_CHISELED_COPPER = register(new Block("waxed_exposed_chiseled_copper", builder())); + public static final Block WAXED_CHISELED_COPPER = register(new Block("waxed_chiseled_copper", builder())); + public static final Block OXIDIZED_CUT_COPPER_STAIRS = register(new Block("oxidized_cut_copper_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block WEATHERED_CUT_COPPER_STAIRS = register(new Block("weathered_cut_copper_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block EXPOSED_CUT_COPPER_STAIRS = register(new Block("exposed_cut_copper_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block CUT_COPPER_STAIRS = register(new Block("cut_copper_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block OXIDIZED_CUT_COPPER_SLAB = register(new Block("oxidized_cut_copper_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block WEATHERED_CUT_COPPER_SLAB = register(new Block("weathered_cut_copper_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block EXPOSED_CUT_COPPER_SLAB = register(new Block("exposed_cut_copper_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block CUT_COPPER_SLAB = register(new Block("cut_copper_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block WAXED_COPPER_BLOCK = register(new Block("waxed_copper_block", builder())); + public static final Block WAXED_WEATHERED_COPPER = register(new Block("waxed_weathered_copper", builder())); + public static final Block WAXED_EXPOSED_COPPER = register(new Block("waxed_exposed_copper", builder())); + public static final Block WAXED_OXIDIZED_COPPER = register(new Block("waxed_oxidized_copper", builder())); + public static final Block WAXED_OXIDIZED_CUT_COPPER = register(new Block("waxed_oxidized_cut_copper", builder())); + public static final Block WAXED_WEATHERED_CUT_COPPER = register(new Block("waxed_weathered_cut_copper", builder())); + public static final Block WAXED_EXPOSED_CUT_COPPER = register(new Block("waxed_exposed_cut_copper", builder())); + public static final Block WAXED_CUT_COPPER = register(new Block("waxed_cut_copper", builder())); + public static final Block WAXED_OXIDIZED_CUT_COPPER_STAIRS = register(new Block("waxed_oxidized_cut_copper_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block WAXED_WEATHERED_CUT_COPPER_STAIRS = register(new Block("waxed_weathered_cut_copper_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block WAXED_EXPOSED_CUT_COPPER_STAIRS = register(new Block("waxed_exposed_cut_copper_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block WAXED_CUT_COPPER_STAIRS = register(new Block("waxed_cut_copper_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block WAXED_OXIDIZED_CUT_COPPER_SLAB = register(new Block("waxed_oxidized_cut_copper_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block WAXED_WEATHERED_CUT_COPPER_SLAB = register(new Block("waxed_weathered_cut_copper_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block WAXED_EXPOSED_CUT_COPPER_SLAB = register(new Block("waxed_exposed_cut_copper_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block WAXED_CUT_COPPER_SLAB = register(new Block("waxed_cut_copper_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block COPPER_DOOR = register(new Block("copper_door", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") + .enumState(DOOR_HINGE, "left", "right") + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block EXPOSED_COPPER_DOOR = register(new Block("exposed_copper_door", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") + .enumState(DOOR_HINGE, "left", "right") + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block OXIDIZED_COPPER_DOOR = register(new Block("oxidized_copper_door", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") + .enumState(DOOR_HINGE, "left", "right") + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block WEATHERED_COPPER_DOOR = register(new Block("weathered_copper_door", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") + .enumState(DOOR_HINGE, "left", "right") + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block WAXED_COPPER_DOOR = register(new Block("waxed_copper_door", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") + .enumState(DOOR_HINGE, "left", "right") + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block WAXED_EXPOSED_COPPER_DOOR = register(new Block("waxed_exposed_copper_door", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") + .enumState(DOOR_HINGE, "left", "right") + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block WAXED_OXIDIZED_COPPER_DOOR = register(new Block("waxed_oxidized_copper_door", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") + .enumState(DOOR_HINGE, "left", "right") + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block WAXED_WEATHERED_COPPER_DOOR = register(new Block("waxed_weathered_copper_door", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") + .enumState(DOOR_HINGE, "left", "right") + .booleanState(OPEN) + .booleanState(POWERED))); + public static final Block COPPER_TRAPDOOR = register(new Block("copper_trapdoor", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .booleanState(OPEN) + .booleanState(POWERED) + .booleanState(WATERLOGGED))); + public static final Block EXPOSED_COPPER_TRAPDOOR = register(new Block("exposed_copper_trapdoor", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .booleanState(OPEN) + .booleanState(POWERED) + .booleanState(WATERLOGGED))); + public static final Block OXIDIZED_COPPER_TRAPDOOR = register(new Block("oxidized_copper_trapdoor", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .booleanState(OPEN) + .booleanState(POWERED) + .booleanState(WATERLOGGED))); + public static final Block WEATHERED_COPPER_TRAPDOOR = register(new Block("weathered_copper_trapdoor", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .booleanState(OPEN) + .booleanState(POWERED) + .booleanState(WATERLOGGED))); + public static final Block WAXED_COPPER_TRAPDOOR = register(new Block("waxed_copper_trapdoor", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .booleanState(OPEN) + .booleanState(POWERED) + .booleanState(WATERLOGGED))); + public static final Block WAXED_EXPOSED_COPPER_TRAPDOOR = register(new Block("waxed_exposed_copper_trapdoor", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .booleanState(OPEN) + .booleanState(POWERED) + .booleanState(WATERLOGGED))); + public static final Block WAXED_OXIDIZED_COPPER_TRAPDOOR = register(new Block("waxed_oxidized_copper_trapdoor", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .booleanState(OPEN) + .booleanState(POWERED) + .booleanState(WATERLOGGED))); + public static final Block WAXED_WEATHERED_COPPER_TRAPDOOR = register(new Block("waxed_weathered_copper_trapdoor", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .booleanState(OPEN) + .booleanState(POWERED) + .booleanState(WATERLOGGED))); + public static final Block COPPER_GRATE = register(new Block("copper_grate", builder() + .booleanState(WATERLOGGED))); + public static final Block EXPOSED_COPPER_GRATE = register(new Block("exposed_copper_grate", builder() + .booleanState(WATERLOGGED))); + public static final Block WEATHERED_COPPER_GRATE = register(new Block("weathered_copper_grate", builder() + .booleanState(WATERLOGGED))); + public static final Block OXIDIZED_COPPER_GRATE = register(new Block("oxidized_copper_grate", builder() + .booleanState(WATERLOGGED))); + public static final Block WAXED_COPPER_GRATE = register(new Block("waxed_copper_grate", builder() + .booleanState(WATERLOGGED))); + public static final Block WAXED_EXPOSED_COPPER_GRATE = register(new Block("waxed_exposed_copper_grate", builder() + .booleanState(WATERLOGGED))); + public static final Block WAXED_WEATHERED_COPPER_GRATE = register(new Block("waxed_weathered_copper_grate", builder() + .booleanState(WATERLOGGED))); + public static final Block WAXED_OXIDIZED_COPPER_GRATE = register(new Block("waxed_oxidized_copper_grate", builder() + .booleanState(WATERLOGGED))); + public static final Block COPPER_BULB = register(new Block("copper_bulb", builder() + .booleanState(LIT) + .booleanState(POWERED))); + public static final Block EXPOSED_COPPER_BULB = register(new Block("exposed_copper_bulb", builder() + .booleanState(LIT) + .booleanState(POWERED))); + public static final Block WEATHERED_COPPER_BULB = register(new Block("weathered_copper_bulb", builder() + .booleanState(LIT) + .booleanState(POWERED))); + public static final Block OXIDIZED_COPPER_BULB = register(new Block("oxidized_copper_bulb", builder() + .booleanState(LIT) + .booleanState(POWERED))); + public static final Block WAXED_COPPER_BULB = register(new Block("waxed_copper_bulb", builder() + .booleanState(LIT) + .booleanState(POWERED))); + public static final Block WAXED_EXPOSED_COPPER_BULB = register(new Block("waxed_exposed_copper_bulb", builder() + .booleanState(LIT) + .booleanState(POWERED))); + public static final Block WAXED_WEATHERED_COPPER_BULB = register(new Block("waxed_weathered_copper_bulb", builder() + .booleanState(LIT) + .booleanState(POWERED))); + public static final Block WAXED_OXIDIZED_COPPER_BULB = register(new Block("waxed_oxidized_copper_bulb", builder() + .booleanState(LIT) + .booleanState(POWERED))); + public static final Block LIGHTNING_ROD = register(new Block("lightning_rod", builder() + .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) + .booleanState(POWERED) + .booleanState(WATERLOGGED))); + public static final Block POINTED_DRIPSTONE = register(new Block("pointed_dripstone", builder() + .enumState(DRIPSTONE_THICKNESS, "tip_merge", "tip", "frustum", "middle", "base") + .enumState(VERTICAL_DIRECTION, Direction.UP, Direction.DOWN) + .booleanState(WATERLOGGED))); + public static final Block DRIPSTONE_BLOCK = register(new Block("dripstone_block", builder())); + public static final Block CAVE_VINES = register(new Block("cave_vines", builder() + .intState(AGE_25, 0, 25) + .booleanState(BERRIES))); + public static final Block CAVE_VINES_PLANT = register(new Block("cave_vines_plant", builder() + .booleanState(BERRIES))); + public static final Block SPORE_BLOSSOM = register(new Block("spore_blossom", builder())); + public static final Block AZALEA = register(new Block("azalea", builder())); + public static final Block FLOWERING_AZALEA = register(new Block("flowering_azalea", builder())); + public static final Block MOSS_CARPET = register(new Block("moss_carpet", builder())); + public static final Block PINK_PETALS = register(new Block("pink_petals", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .intState(FLOWER_AMOUNT, 1, 4))); + public static final Block MOSS_BLOCK = register(new Block("moss_block", builder())); + public static final Block BIG_DRIPLEAF = register(new Block("big_dripleaf", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(TILT, "none", "unstable", "partial", "full") + .booleanState(WATERLOGGED))); + public static final Block BIG_DRIPLEAF_STEM = register(new Block("big_dripleaf_stem", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block SMALL_DRIPLEAF = register(new Block("small_dripleaf", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") + .booleanState(WATERLOGGED))); + public static final Block HANGING_ROOTS = register(new Block("hanging_roots", builder() + .booleanState(WATERLOGGED))); + public static final Block ROOTED_DIRT = register(new Block("rooted_dirt", builder())); + public static final Block MUD = register(new Block("mud", builder())); + public static final Block DEEPSLATE = register(new Block("deepslate", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block COBBLED_DEEPSLATE = register(new Block("cobbled_deepslate", builder())); + public static final Block COBBLED_DEEPSLATE_STAIRS = register(new Block("cobbled_deepslate_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block COBBLED_DEEPSLATE_SLAB = register(new Block("cobbled_deepslate_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block COBBLED_DEEPSLATE_WALL = register(new Block("cobbled_deepslate_wall", builder() + .enumState(EAST_WALL, "none", "low", "tall") + .enumState(NORTH_WALL, "none", "low", "tall") + .enumState(SOUTH_WALL, "none", "low", "tall") + .booleanState(UP) + .booleanState(WATERLOGGED) + .enumState(WEST_WALL, "none", "low", "tall"))); + public static final Block POLISHED_DEEPSLATE = register(new Block("polished_deepslate", builder())); + public static final Block POLISHED_DEEPSLATE_STAIRS = register(new Block("polished_deepslate_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block POLISHED_DEEPSLATE_SLAB = register(new Block("polished_deepslate_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block POLISHED_DEEPSLATE_WALL = register(new Block("polished_deepslate_wall", builder() + .enumState(EAST_WALL, "none", "low", "tall") + .enumState(NORTH_WALL, "none", "low", "tall") + .enumState(SOUTH_WALL, "none", "low", "tall") + .booleanState(UP) + .booleanState(WATERLOGGED) + .enumState(WEST_WALL, "none", "low", "tall"))); + public static final Block DEEPSLATE_TILES = register(new Block("deepslate_tiles", builder())); + public static final Block DEEPSLATE_TILE_STAIRS = register(new Block("deepslate_tile_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block DEEPSLATE_TILE_SLAB = register(new Block("deepslate_tile_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block DEEPSLATE_TILE_WALL = register(new Block("deepslate_tile_wall", builder() + .enumState(EAST_WALL, "none", "low", "tall") + .enumState(NORTH_WALL, "none", "low", "tall") + .enumState(SOUTH_WALL, "none", "low", "tall") + .booleanState(UP) + .booleanState(WATERLOGGED) + .enumState(WEST_WALL, "none", "low", "tall"))); + public static final Block DEEPSLATE_BRICKS = register(new Block("deepslate_bricks", builder())); + public static final Block DEEPSLATE_BRICK_STAIRS = register(new Block("deepslate_brick_stairs", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .enumState(HALF, "top", "bottom") + .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .booleanState(WATERLOGGED))); + public static final Block DEEPSLATE_BRICK_SLAB = register(new Block("deepslate_brick_slab", builder() + .enumState(SLAB_TYPE, "top", "bottom", "double") + .booleanState(WATERLOGGED))); + public static final Block DEEPSLATE_BRICK_WALL = register(new Block("deepslate_brick_wall", builder() + .enumState(EAST_WALL, "none", "low", "tall") + .enumState(NORTH_WALL, "none", "low", "tall") + .enumState(SOUTH_WALL, "none", "low", "tall") + .booleanState(UP) + .booleanState(WATERLOGGED) + .enumState(WEST_WALL, "none", "low", "tall"))); + public static final Block CHISELED_DEEPSLATE = register(new Block("chiseled_deepslate", builder())); + public static final Block CRACKED_DEEPSLATE_BRICKS = register(new Block("cracked_deepslate_bricks", builder())); + public static final Block CRACKED_DEEPSLATE_TILES = register(new Block("cracked_deepslate_tiles", builder())); + public static final Block INFESTED_DEEPSLATE = register(new Block("infested_deepslate", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block SMOOTH_BASALT = register(new Block("smooth_basalt", builder())); + public static final Block RAW_IRON_BLOCK = register(new Block("raw_iron_block", builder())); + public static final Block RAW_COPPER_BLOCK = register(new Block("raw_copper_block", builder())); + public static final Block RAW_GOLD_BLOCK = register(new Block("raw_gold_block", builder())); + public static final Block POTTED_AZALEA_BUSH = register(new Block("potted_azalea_bush", builder())); + public static final Block POTTED_FLOWERING_AZALEA_BUSH = register(new Block("potted_flowering_azalea_bush", builder())); + public static final Block OCHRE_FROGLIGHT = register(new Block("ochre_froglight", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block VERDANT_FROGLIGHT = register(new Block("verdant_froglight", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block PEARLESCENT_FROGLIGHT = register(new Block("pearlescent_froglight", builder() + .enumState(AXIS, Axis.VALUES))); + public static final Block FROGSPAWN = register(new Block("frogspawn", builder())); + public static final Block REINFORCED_DEEPSLATE = register(new Block("reinforced_deepslate", builder())); + public static final Block DECORATED_POT = register(new Block("decorated_pot", builder() + .booleanState(CRACKED) + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(WATERLOGGED))); + public static final Block CRAFTER = register(new Block("crafter", builder() + .booleanState(CRAFTING) + .enumState(ORIENTATION, "down_east", "down_north", "down_south", "down_west", "up_east", "up_north", "up_south", "up_west", "west_up", "east_up", "north_up", "south_up") + .booleanState(TRIGGERED))); + public static final Block TRIAL_SPAWNER = register(new Block("trial_spawner", builder() + .booleanState(OMINOUS) + .enumState(TRIAL_SPAWNER_STATE, "inactive", "waiting_for_players", "active", "waiting_for_reward_ejection", "ejecting_reward", "cooldown"))); + public static final Block VAULT = register(new Block("vault", builder() + .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) + .booleanState(OMINOUS) + .enumState(VAULT_STATE, "inactive", "active", "unlocking", "ejecting"))); + public static final Block HEAVY_CORE = register(new Block("heavy_core", builder() + .booleanState(WATERLOGGED))); + + private static T register(T block) { + BlockRegistries.JAVA_BLOCKS_TO_RENAME.get().add(block); + return block; + } + + private Blocks() { + } +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/ChestType.java b/core/src/main/java/org/geysermc/geyser/level/block/property/ChestType.java new file mode 100644 index 000000000..c206f127c --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/property/ChestType.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 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.level.block.property; + +public enum ChestType { + SINGLE, + LEFT, + RIGHT; + + public static final ChestType[] VALUES = values(); +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java b/core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java new file mode 100644 index 000000000..bbb6f8fe3 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 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.level.block.property; + +import org.geysermc.geyser.level.physics.Axis; +import org.geysermc.geyser.level.physics.Direction; + +public final class Properties { + public static final Property ATTACHED = Property.create("attached"); + public static final Property BOTTOM = Property.create("bottom"); + public static final Property CONDITIONAL = Property.create("conditional"); + public static final Property DISARMED = Property.create("disarmed"); + public static final Property DRAG = Property.create("drag"); + public static final Property ENABLED = Property.create("enabled"); + public static final Property EXTENDED = Property.create("extended"); + public static final Property EYE = Property.create("eye"); + public static final Property FALLING = Property.create("falling"); + public static final Property HANGING = Property.create("hanging"); + public static final Property HAS_BOTTLE_0 = Property.create("has_bottle_0"); + public static final Property HAS_BOTTLE_1 = Property.create("has_bottle_1"); + public static final Property HAS_BOTTLE_2 = Property.create("has_bottle_2"); + public static final Property HAS_RECORD = Property.create("has_record"); + public static final Property HAS_BOOK = Property.create("has_book"); + public static final Property INVERTED = Property.create("inverted"); + public static final Property IN_WALL = Property.create("in_wall"); + public static final Property LIT = Property.create("lit"); + public static final Property LOCKED = Property.create("locked"); + public static final Property OCCUPIED = Property.create("occupied"); + public static final Property OPEN = Property.create("open"); + public static final Property PERSISTENT = Property.create("persistent"); + public static final Property POWERED = Property.create("powered"); + public static final Property SHORT = Property.create("short"); + public static final Property SIGNAL_FIRE = Property.create("signal_fire"); + public static final Property SNOWY = Property.create("snowy"); + public static final Property TRIGGERED = Property.create("triggered"); + public static final Property UNSTABLE = Property.create("unstable"); + public static final Property WATERLOGGED = Property.create("waterlogged"); + public static final Property BERRIES = Property.create("berries"); + public static final Property BLOOM = Property.create("bloom"); + public static final Property SHRIEKING = Property.create("shrieking"); + public static final Property CAN_SUMMON = Property.create("can_summon"); + public static final Property HORIZONTAL_AXIS = Property.create("axis"); + public static final Property AXIS = Property.create("axis"); + public static final Property UP = Property.create("up"); + public static final Property DOWN = Property.create("down"); + public static final Property NORTH = Property.create("north"); + public static final Property EAST = Property.create("east"); + public static final Property SOUTH = Property.create("south"); + public static final Property WEST = Property.create("west"); + public static final Property FACING = Property.create("facing"); + public static final Property FACING_HOPPER = Property.create("facing"); + public static final Property HORIZONTAL_FACING = Property.create("facing"); + public static final Property FLOWER_AMOUNT = Property.create("flower_amount"); + public static final Property ORIENTATION = Property.create("orientation"); + public static final Property ATTACH_FACE = Property.create("face"); + public static final Property BELL_ATTACHMENT = Property.create("attachment"); + public static final Property EAST_WALL = Property.create("east"); + public static final Property NORTH_WALL = Property.create("north"); + public static final Property SOUTH_WALL = Property.create("south"); + public static final Property WEST_WALL = Property.create("west"); + public static final Property EAST_REDSTONE = Property.create("east"); + public static final Property NORTH_REDSTONE = Property.create("north"); + public static final Property SOUTH_REDSTONE = Property.create("south"); + public static final Property WEST_REDSTONE = Property.create("west"); + public static final Property DOUBLE_BLOCK_HALF = Property.create("half"); + public static final Property HALF = Property.create("half"); + public static final Property RAIL_SHAPE = Property.create("shape"); + public static final Property RAIL_SHAPE_STRAIGHT = Property.create("shape"); + public static final Property AGE_1 = Property.create("age"); + public static final Property AGE_2 = Property.create("age"); + public static final Property AGE_3 = Property.create("age"); + public static final Property AGE_4 = Property.create("age"); + public static final Property AGE_5 = Property.create("age"); + public static final Property AGE_7 = Property.create("age"); + public static final Property AGE_15 = Property.create("age"); + public static final Property AGE_25 = Property.create("age"); + public static final Property BITES = Property.create("bites"); + public static final Property CANDLES = Property.create("candles"); + public static final Property DELAY = Property.create("delay"); + public static final Property DISTANCE = Property.create("distance"); + public static final Property EGGS = Property.create("eggs"); + public static final Property HATCH = Property.create("hatch"); + public static final Property LAYERS = Property.create("layers"); + public static final Property LEVEL_CAULDRON = Property.create("level"); + public static final Property LEVEL_COMPOSTER = Property.create("level"); + public static final Property LEVEL_FLOWING = Property.create("level"); + public static final Property LEVEL_HONEY = Property.create("honey_level"); + public static final Property LEVEL = Property.create("level"); + public static final Property MOISTURE = Property.create("moisture"); + public static final Property NOTE = Property.create("note"); + public static final Property PICKLES = Property.create("pickles"); + public static final Property POWER = Property.create("power"); + public static final Property STAGE = Property.create("stage"); + public static final Property STABILITY_DISTANCE = Property.create("distance"); + public static final Property RESPAWN_ANCHOR_CHARGES = Property.create("charges"); + public static final Property ROTATION_16 = Property.create("rotation"); + public static final Property BED_PART = Property.create("part"); + public static final Property CHEST_TYPE = Property.create("type"); + public static final Property MODE_COMPARATOR = Property.create("mode"); + public static final Property DOOR_HINGE = Property.create("hinge"); + public static final Property NOTEBLOCK_INSTRUMENT = Property.create("instrument"); + public static final Property PISTON_TYPE = Property.create("type"); + public static final Property SLAB_TYPE = Property.create("type"); + public static final Property STAIRS_SHAPE = Property.create("shape"); + public static final Property STRUCTUREBLOCK_MODE = Property.create("mode"); + public static final Property BAMBOO_LEAVES = Property.create("leaves"); + public static final Property TILT = Property.create("tilt"); + public static final Property VERTICAL_DIRECTION = Property.create("vertical_direction"); + public static final Property DRIPSTONE_THICKNESS = Property.create("thickness"); + public static final Property SCULK_SENSOR_PHASE = Property.create("sculk_sensor_phase"); + public static final Property CHISELED_BOOKSHELF_SLOT_0_OCCUPIED = Property.create("slot_0_occupied"); + public static final Property CHISELED_BOOKSHELF_SLOT_1_OCCUPIED = Property.create("slot_1_occupied"); + public static final Property CHISELED_BOOKSHELF_SLOT_2_OCCUPIED = Property.create("slot_2_occupied"); + public static final Property CHISELED_BOOKSHELF_SLOT_3_OCCUPIED = Property.create("slot_3_occupied"); + public static final Property CHISELED_BOOKSHELF_SLOT_4_OCCUPIED = Property.create("slot_4_occupied"); + public static final Property CHISELED_BOOKSHELF_SLOT_5_OCCUPIED = Property.create("slot_5_occupied"); + public static final Property DUSTED = Property.create("dusted"); + public static final Property CRACKED = Property.create("cracked"); + public static final Property CRAFTING = Property.create("crafting"); + public static final Property TRIAL_SPAWNER_STATE = Property.create("trial_spawner_state"); + public static final Property VAULT_STATE = Property.create("vault_state"); + public static final Property OMINOUS = Property.create("ominous"); +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/Property.java b/core/src/main/java/org/geysermc/geyser/level/block/property/Property.java new file mode 100644 index 000000000..da68c54e4 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/property/Property.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 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.level.block.property; + +public class Property> { + private final String name; + + public Property(String name) { + this.name = name; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "[" + name + "]"; + } + + public static > Property create(String name) { + return new Property<>(name); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/BannerBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/BannerBlock.java new file mode 100644 index 000000000..481004baa --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/BannerBlock.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 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.level.block.type; + +public class BannerBlock extends Block { + private final int dyeColor; + + public BannerBlock(String javaIdentifier, int dyeColor, Builder builder) { + super(javaIdentifier, builder); + this.dyeColor = dyeColor; + } + + public int dyeColor() { + return dyeColor; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/BedBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/BedBlock.java new file mode 100644 index 000000000..e72dbdafa --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/BedBlock.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 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.level.block.type; + +public class BedBlock extends Block { + private final int dyeColor; + + public BedBlock(String javaIdentifier, int dyeColor, Builder builder) { + super(javaIdentifier, builder); + this.dyeColor = dyeColor; + } + + public int dyeColor() { + return dyeColor; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java b/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java new file mode 100644 index 000000000..459f4a5af --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 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.level.block.type; + +import it.unimi.dsi.fastutil.Pair; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; +import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap; +import it.unimi.dsi.fastutil.objects.Reference2ObjectMap; +import org.geysermc.geyser.level.block.property.Property; +import org.geysermc.geyser.registry.BlockRegistries; +import org.geysermc.mcprotocollib.protocol.data.game.Identifier; + +import java.util.*; +import java.util.stream.Stream; + +public class Block { + public static final int JAVA_AIR_ID = 0; + + private final String javaIdentifier; + private int javaId = -1; + + public Block(String javaIdentifier, Builder builder) { + this.javaIdentifier = Identifier.formalize(javaIdentifier).intern(); + builder.build(this); + } + + public String javaIdentifier() { + return javaIdentifier; + } + + public int javaId() { + return javaId; + } + + public void setJavaId(int javaId) { + if (this.javaId != -1) { + throw new RuntimeException("Block ID has already been set!"); + } + this.javaId = javaId; + } + + @Override + public String toString() { + return "Item{" + + "javaIdentifier='" + javaIdentifier + '\'' + + ", javaId=" + javaId + + '}'; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private final Map, List>> states = new LinkedHashMap<>(); + + /** + * For states that we're just tracking for mirroring Java states. + */ + public Builder enumState(Property property, String... values) { + states.put(property, List.of(values)); + return this; + } + + @SafeVarargs + public final > Builder enumState(Property property, T... enums) { + states.put(property, List.of(enums)); + return this; + } + + public Builder booleanState(Property property) { + states.put(property, List.of(Boolean.TRUE, Boolean.FALSE)); // Make this list a static constant if it'll survive past initialization + return this; + } + + public Builder intState(Property property, int low, int high) { + IntList list = new IntArrayList(); + // There is a state for every number between the low and high. + for (int i = low; i <= high; i++) { + list.add(i); + } + states.put(property, List.copyOf(list)); // Boxing reasons for that copy I guess. + return this; + } + + private void build(Block block) { + if (states.isEmpty()) { + BlockRegistries.BLOCK_STATES.get().add(new BlockState(block, BlockRegistries.BLOCK_STATES.get().size())); + } else { + // Think of this stream as another list containing, at the start, one empty list. + // It's two collections. Not a stream from the empty list. + Stream, Comparable>>> stream = Stream.of(Collections.emptyList()); + for (var state : this.states.entrySet()) { + // OK, so here's how I understand this works. Because this was staring at vanilla Java code trying + // to figure out exactly how it works so we don't have any discrepencies. + // For each existing pair in the list, a new list is created, adding one of the new values. + // Property up [true/false] would exist as true and false + // Both entries will get duplicated, adding down, true and false. + stream = stream.flatMap(aPreviousPropertiesList -> + // So the above is a list. It may be empty if this is the first property, + // or it may be populated if this is not the first property. + // We're about to create a new stream, each with a new list, + // for every previous property + state.getValue().stream().map(value -> { + var newProperties = new ArrayList<>(aPreviousPropertiesList); + newProperties.add(Pair.of(state.getKey(), value)); + return newProperties; + })); + } + + // Now we have a list of Pairs. Each list is a block state! + // If we have two boolean properties: up [true/false] and down [true/false], + // We'll see [up=true,down=true], [up=false,down=true], [up=true,down=false], [up=false,down=false] + stream.forEach(properties -> { + Reference2ObjectMap, Comparable> propertyMap = new Reference2ObjectArrayMap<>(properties.size()); + for (int i = 0; i < properties.size(); i++) { + Pair, Comparable> property = properties.get(i); + propertyMap.put(property.key(), property.value()); + } + BlockRegistries.BLOCK_STATES.get().add(new BlockState(block, BlockRegistries.BLOCK_STATES.get().size(), propertyMap)); + }); + } + } + + private Builder() { + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java new file mode 100644 index 000000000..936b711e4 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 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.level.block.type; + +import it.unimi.dsi.fastutil.objects.Reference2ObjectMap; +import it.unimi.dsi.fastutil.objects.Reference2ObjectMaps; +import org.geysermc.geyser.level.block.property.Property; +import org.geysermc.geyser.registry.BlockRegistries; + +public final class BlockState { + private final Block block; + private final int javaId; + private final Reference2ObjectMap, Comparable> states; + + BlockState(Block block, int javaId) { + this(block, javaId, Reference2ObjectMaps.emptyMap()); + } + + BlockState(Block block, int javaId, Reference2ObjectMap, Comparable> states) { + this.block = block; + this.javaId = javaId; + this.states = states; + } + + public > T getValue(Property property) { + //noinspection unchecked + return (T) states.get(property); + } + + public Block block() { + return block; + } + + public int javaId() { + return javaId; + } + + public static BlockState of(int javaId) { + return BlockRegistries.BLOCK_STATES.get(javaId); + } +} 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 aa9d6fc36..54a36dc12 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java +++ b/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java @@ -34,6 +34,8 @@ 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.JavaBlockState; +import org.geysermc.geyser.level.block.type.Block; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.registry.loader.CollisionRegistryLoader; import org.geysermc.geyser.registry.loader.RegistryLoaders; import org.geysermc.geyser.registry.populator.BlockRegistryPopulator; @@ -44,8 +46,8 @@ import org.geysermc.geyser.registry.type.BlockMappings; import org.geysermc.geyser.registry.type.CustomSkull; import org.geysermc.geyser.translator.collision.BlockCollision; +import java.util.ArrayList; import java.util.BitSet; - import java.util.Set; /** @@ -58,6 +60,14 @@ public class BlockRegistries { */ public static final VersionedRegistry BLOCKS = VersionedRegistry.create(RegistryLoaders.empty(Int2ObjectOpenHashMap::new)); + /** + * A registry which stores Java IDs to Java {@link BlockState}s, each with their specific state differences and a link + * to the overarching block. + */ + public static final ListRegistry BLOCK_STATES = ListRegistry.create(RegistryLoaders.empty(ArrayList::new)); + + public static final ListRegistry JAVA_BLOCKS_TO_RENAME = ListRegistry.create(RegistryLoaders.empty(ArrayList::new)); + /** * A mapped registry which stores Java to Bedrock block identifiers. */ diff --git a/core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java new file mode 100644 index 000000000..bb5d2538c --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 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; + +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.registry.loader.RegistryLoader; + +import java.util.List; + +public class ListRegistry extends Registry> { + /** + * Creates a new instance of this class with the given input and + * {@link RegistryLoader}. The input specified is what the registry + * loader needs to take in. + * + * @param input the input + * @param registryLoader the registry loader + */ + protected ListRegistry(I input, RegistryLoader> registryLoader) { + super(input, registryLoader); + } + + /** + * Returns the value registered by the given index. + * + * @param index the index + * @return the value registered by the given index. + */ + @Nullable + public M get(int index) { + if (index >= this.mappings.size()) { + return null; + } + + return this.mappings.get(index); + } + + /** + * Returns the value registered by the given index or the default value + * specified if null. + * + * @param index the index + * @param defaultValue the default value + * @return the value registered by the given key or the default value + * specified if null. + */ + public M getOrDefault(int index, M defaultValue) { + M value = this.get(index); + if (value == null) { + return defaultValue; + } + + return value; + } + + /** + * Registers a new value into this registry with the given index. + * + * @param index the index + * @param value the value + * @return a new value into this registry with the given index. + */ + public M register(int index, M value) { + return this.mappings.set(index, value); + } + + /** + * Creates a new array registry with the given {@link RegistryLoader}. The + * input type is not specified here, meaning the loader return type is either + * predefined, or the registry is populated at a later point. + * + * @param registryLoader the registry loader + * @param the input type + * @param the returned mappings type + * @return a new registry with the given RegistryLoader supplier + */ + public static ListRegistry create(RegistryLoader> registryLoader) { + return new ListRegistry(null, registryLoader); + } +} 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 e76edc059..ace110f78 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 @@ -582,8 +582,6 @@ public final class BlockRegistryPopulator { } } - BlockRegistries.CLEAN_JAVA_IDENTIFIERS.set(cleanIdentifiers.toArray(new String[0])); - BLOCKS_JSON = blocksJson; JsonNode blockInteractionsJson; 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 c0ff1fb71..144cd9f27 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -1592,9 +1592,6 @@ 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); } 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 e3a9cba89..7b279857a 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,6 +25,7 @@ package org.geysermc.geyser.session.cache; +import org.geysermc.geyser.level.block.type.Block; import org.geysermc.mcprotocollib.protocol.data.game.chunk.DataPalette; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; @@ -92,11 +93,11 @@ public class ChunkCache { DataPalette palette = chunk.sections()[(y - minY) >> 4]; if (palette == null) { - if (block != BlockStateValues.JAVA_AIR_ID) { + if (block != Block.JAVA_AIR_ID) { // A previously empty chunk, which is no longer empty as a block has been added to it palette = DataPalette.createForChunk(); // Fixes the chunk assuming that all blocks is the `block` variable we are updating. /shrug - palette.getPalette().stateToId(BlockStateValues.JAVA_AIR_ID); + palette.getPalette().stateToId(Block.JAVA_AIR_ID); chunk.sections()[(y - minY) >> 4] = palette; } else { // Nothing to update @@ -109,17 +110,17 @@ public class ChunkCache { public int getBlockAt(int x, int y, int z) { if (!cache) { - return BlockStateValues.JAVA_AIR_ID; + return Block.JAVA_AIR_ID; } GeyserChunk column = this.getChunk(x >> 4, z >> 4); if (column == null) { - return BlockStateValues.JAVA_AIR_ID; + return Block.JAVA_AIR_ID; } if (y < minY || ((y - minY) >> 4) > column.sections().length - 1) { // Y likely goes above or below the height limit of this world - return BlockStateValues.JAVA_AIR_ID; + return Block.JAVA_AIR_ID; } DataPalette chunk = column.sections()[(y - minY) >> 4]; @@ -127,7 +128,7 @@ public class ChunkCache { return chunk.get(x & 0xF, y & 0xF, z & 0xF); } - return BlockStateValues.JAVA_AIR_ID; + return Block.JAVA_AIR_ID; } public void removeChunk(int chunkX, int chunkZ) { 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 f9879499a..795eba101 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 @@ -35,6 +35,7 @@ import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.holder.BlockInventoryHolder; import org.geysermc.geyser.inventory.updater.ContainerInventoryUpdater; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator; @@ -58,7 +59,7 @@ public class ShulkerInventoryTranslator extends AbstractBlockInventoryTranslator .putInt("z", position.getZ()) .putString("CustomName", inventory.getTitle()); // Don't reset facing property - shulkerBoxTranslator.translateTag(session, tag, null, javaBlockState); + shulkerBoxTranslator.translateTag(session, tag, null, BlockState.of(javaBlockState)); BlockEntityDataPacket dataPacket = new BlockEntityDataPacket(); dataPacket.setData(tag.build()); 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 498bd418b..cb973fa18 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 @@ -36,8 +36,7 @@ import org.cloudburstmc.protocol.bedrock.packet.ContainerOpenPacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.geyser.inventory.Container; import org.geysermc.geyser.inventory.Inventory; -import org.geysermc.geyser.level.block.BlockStateValues; -import org.geysermc.geyser.level.block.DoubleChestValue; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.type.BlockMapping; import org.geysermc.geyser.session.GeyserSession; @@ -72,8 +71,8 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator { .putString("CustomName", inventory.getTitle()) .putString("id", "Chest"); - DoubleChestValue chestValue = BlockStateValues.getDoubleChestValues().get(javaBlockId); - DoubleChestBlockEntityTranslator.translateChestValue(tag, chestValue, + BlockState blockState = BlockState.of(javaBlockId); + DoubleChestBlockEntityTranslator.translateChestValue(tag, blockState, session.getLastInteractionBlockPosition().getX(), session.getLastInteractionBlockPosition().getZ()); BlockEntityDataPacket dataPacket = new BlockEntityDataPacket(); 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 81f58214c..8b6f627e1 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 @@ -30,7 +30,8 @@ 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.level.block.type.BannerBlock; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @@ -39,10 +40,9 @@ import java.util.List; @BlockEntity(type = BlockEntityType.BANNER) public class BannerBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { @Override - 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); + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, BlockState blockState) { + if (blockState.block() instanceof BannerBlock banner) { + bedrockNbt.putInt("Base", 15 - banner.dyeColor()); } if (javaNbt == null) { 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 f7dee2864..9b5248785 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 @@ -27,13 +27,14 @@ package org.geysermc.geyser.translator.level.block.entity; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; +import org.geysermc.geyser.level.block.type.BlockState; 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(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) { int primary = javaNbt.getInt("primary"); // The effects here generally map one-to-one Java <-> Bedrock. Only the newer ones get more complicated bedrockNbt.putInt("primary", primary == -1 ? 0 : primary); 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 720ffea3c..7622e6d28 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 @@ -27,19 +27,15 @@ package org.geysermc.geyser.translator.level.block.entity; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; -import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.type.BedBlock; +import org.geysermc.geyser.level.block.type.BlockState; 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(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { - byte bedcolor = BlockStateValues.getBedColor(blockState); - // Just in case... - if (bedcolor == -1) { - bedcolor = 0; - } - bedrockNbt.putByte("color", bedcolor); + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) { + bedrockNbt.putByte("color", (byte) (blockState.block() instanceof BedBlock bed ? bed.dyeColor() : 0)); } } 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 051986473..01e2d3e74 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 @@ -31,6 +31,7 @@ import org.cloudburstmc.nbt.NbtList; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtType; import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; /** @@ -50,7 +51,7 @@ public interface BedrockOnlyBlockEntity extends RequiresBlockState { * @param blockState The Java block state. * @param position The Bedrock block position. */ - void updateBlock(GeyserSession session, int blockState, Vector3i position); + void updateBlock(GeyserSession session, BlockState blockState, Vector3i position); /** * Get the tag of the Bedrock-only block entity 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 6df7781be..5def51e01 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 @@ -28,6 +28,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.type.BlockState; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.BlockEntityUtils; import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @@ -39,9 +40,9 @@ public abstract class BlockEntityTranslator { protected BlockEntityTranslator() { } - public abstract void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState); + public abstract void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState); - public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, @Nullable NbtMap javaNbt, int blockState) { + public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, @Nullable NbtMap javaNbt, BlockState blockState) { NbtMapBuilder tagBuilder = getConstantBedrockTag(type, x, y, z); if (javaNbt != null || this instanceof RequiresBlockState) { // Always process tags if the block state is part of the tag. 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 b4012236b..f0d632041 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 @@ -29,7 +29,8 @@ import org.checkerframework.checker.nullness.qual.Nullable; 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.level.block.property.Properties; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @@ -38,7 +39,7 @@ 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, @Nullable NbtMap javaNbt, int blockState) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, BlockState blockState) { if (javaNbt == null) { return; } @@ -70,6 +71,6 @@ public class BrushableBlockEntityTranslator extends BlockEntityTranslator implem // controls which side the item protrudes from bedrockNbt.putByte("brush_direction", hitDirection); // controls how much the item protrudes - bedrockNbt.putInt("brush_count", BlockStateValues.getBrushProgress(blockState)); + bedrockNbt.putInt("brush_count", blockState.getValue(Properties.DUSTED)); } } 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 699319bb6..fb71a84cc 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 @@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.level.block.entity; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; @@ -38,7 +39,7 @@ import java.util.List; @BlockEntity(type = BlockEntityType.CAMPFIRE) public class CampfireBlockEntityTranslator extends BlockEntityTranslator { @Override - public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) { List items = javaNbt.getList("Items", NbtType.COMPOUND); if (items != null) { int i = 1; 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 0e00a19a8..b363de530 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 @@ -27,7 +27,8 @@ package org.geysermc.geyser.translator.level.block.entity; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; -import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @@ -35,12 +36,12 @@ 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(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState 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 - bedrockNbt.putByte("conditionalMode", BlockStateValues.getCommandBlockValues().getOrDefault(blockState, (byte) 0)); + bedrockNbt.putBoolean("conditionalMode", blockState.getValue(Properties.CONDITIONAL)); // Java and Bedrock values bedrockNbt.putByte("conditionMet", javaNbt.getByte("conditionMet")); bedrockNbt.putByte("auto", javaNbt.getByte("auto")); 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 b24558b45..33c884c55 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 @@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.level.block.entity; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @@ -35,7 +36,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType public class DecoratedPotBlockEntityTranslator extends BlockEntityTranslator { @Override - public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) { if (javaNbt == null) { return; } 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 dcb39d22c..63c5f71f3 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 @@ -29,7 +29,9 @@ 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; +import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.geyser.level.block.type.BlockState; +import org.geysermc.geyser.level.physics.Direction; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.BlockEntityUtils; import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @@ -45,52 +47,40 @@ public class DoubleChestBlockEntityTranslator extends BlockEntityTranslator impl } @Override - public void updateBlock(GeyserSession session, int blockState, Vector3i position) { + public void updateBlock(GeyserSession session, BlockState blockState, Vector3i position) { NbtMapBuilder tagBuilder = getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId(BlockEntityType.CHEST), position.getX(), position.getY(), position.getZ()); translateTag(session, tagBuilder, null, blockState); BlockEntityUtils.updateBlockEntity(session, tagBuilder.build(), position); } @Override - public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { - DoubleChestValue chestValues = BlockStateValues.getDoubleChestValues().get(blockState); - if (chestValues != null) { - int x = (int) bedrockNbt.get("x"); - int z = (int) bedrockNbt.get("z"); - translateChestValue(bedrockNbt, chestValues, x, z); - } + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) { + int x = (int) bedrockNbt.get("x"); + int z = (int) bedrockNbt.get("z"); + translateChestValue(bedrockNbt, blockState, x, z); } /** * Add Bedrock block entity tags to a NbtMap based on Java properties * * @param builder the NbtMapBuilder to apply properties to - * @param chestValues the position properties of this double chest + * @param state the BlockState of this double chest * @param x the x position of this chest pair * @param z the z position of this chest pair */ - public static void translateChestValue(NbtMapBuilder builder, DoubleChestValue chestValues, int x, int z) { + public static void translateChestValue(NbtMapBuilder builder, BlockState state, int x, int z) { // Calculate the position of the other chest based on the Java block state - if (chestValues.isFacingEast()) { - if (chestValues.isDirectionPositive()) { - // East - z = z + (chestValues.isLeft() ? 1 : -1); - } else { - // West - z = z + (chestValues.isLeft() ? -1 : 1); - } - } else { - if (chestValues.isDirectionPositive()) { - // South - x = x + (chestValues.isLeft() ? -1 : 1); - } else { - // North - x = x + (chestValues.isLeft() ? 1 : -1); - } + Direction facing = state.getValue(Properties.HORIZONTAL_FACING); + boolean isLeft = state.getValue(Properties.CHEST_TYPE).equals("left"); //TODO enum + switch (facing) { + case EAST -> z = z + (isLeft ? 1 : -1); + case WEST -> z = z + (isLeft ? -1 : 1); + case SOUTH -> x = x + (isLeft ? -1 : 1); + case NORTH -> x = x + (isLeft ? 1 : -1); } builder.putInt("pairx", x); builder.putInt("pairz", z); - if (!chestValues.isLeft()) { + if (!isLeft) { 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 9ce0aff0a..88029dc2d 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 @@ -27,10 +27,11 @@ package org.geysermc.geyser.translator.level.block.entity; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; public class EmptyBlockEntityTranslator extends BlockEntityTranslator { @Override - public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState 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 97428eec1..36731bdff 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 @@ -31,13 +31,14 @@ import org.cloudburstmc.nbt.NbtList; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @BlockEntity(type = BlockEntityType.END_GATEWAY) public class EndGatewayBlockEntityTranslator extends BlockEntityTranslator { @Override - public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState 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 diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/FlowerPotBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/FlowerPotBlockEntityTranslator.java index 074fff6ef..0a60b0f32 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/FlowerPotBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/FlowerPotBlockEntityTranslator.java @@ -30,6 +30,7 @@ import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.BlockEntityUtils; @@ -75,12 +76,12 @@ public class FlowerPotBlockEntityTranslator implements BedrockOnlyBlockEntity { } @Override - public void updateBlock(GeyserSession session, int blockState, Vector3i position) { - NbtMap tag = getTag(session, blockState, position); + public void updateBlock(GeyserSession session, BlockState blockState, Vector3i position) { + NbtMap tag = getTag(session, blockState.javaId(), position); BlockEntityUtils.updateBlockEntity(session, tag, position); UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); updateBlockPacket.setDataLayer(0); - updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(blockState)); + updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(blockState.javaId())); updateBlockPacket.setBlockPosition(position); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/JigsawBlockBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/JigsawBlockBlockEntityTranslator.java index 53f32682c..51f5565b7 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 @@ -29,13 +29,14 @@ 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.level.block.type.BlockState; 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(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, int blockState) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, BlockState blockState) { if (javaNbt == null) { return; } @@ -46,7 +47,7 @@ public class JigsawBlockBlockEntityTranslator extends BlockEntityTranslator impl } 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 - bedrockNbt.putString("joint", BlockStateValues.getHorizontalFacingJigsaws().contains(blockState) ? "aligned" : "rollable"); + bedrockNbt.putString("joint", BlockStateValues.getHorizontalFacingJigsaws().contains(blockState.javaId()) ? "aligned" : "rollable"); // TODO } bedrockNbt.putString("name", javaNbt.getString("name")); bedrockNbt.putString("target_pool", javaNbt.getString("target_pool")); 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 78e71000a..e09f6ae42 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,6 +25,7 @@ package org.geysermc.geyser.translator.level.block.entity; +import org.geysermc.geyser.level.block.type.Block; import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType; import org.cloudburstmc.math.vector.Vector3d; import org.cloudburstmc.math.vector.Vector3f; @@ -222,10 +223,10 @@ public class PistonBlockEntity { Vector3i blockInFront = position.add(orientation.getUnitVector()); int blockId = session.getGeyser().getWorldManager().getBlockAt(session, blockInFront); if (BlockStateValues.isPistonHead(blockId)) { - ChunkUtils.updateBlock(session, BlockStateValues.JAVA_AIR_ID, blockInFront); - } else if ((session.getGeyser().getPlatformType() == PlatformType.SPIGOT || session.getErosionHandler().isActive()) && blockId == BlockStateValues.JAVA_AIR_ID) { + ChunkUtils.updateBlock(session, Block.JAVA_AIR_ID, blockInFront); + } else if ((session.getGeyser().getPlatformType() == PlatformType.SPIGOT || session.getErosionHandler().isActive()) && blockId == Block.JAVA_AIR_ID) { // Spigot removes the piston head from the cache, but we need to send the block update ourselves - ChunkUtils.updateBlock(session, BlockStateValues.JAVA_AIR_ID, blockInFront); + ChunkUtils.updateBlock(session, Block.JAVA_AIR_ID, blockInFront); } } @@ -255,7 +256,7 @@ public class PistonBlockEntity { continue; } int blockId = session.getGeyser().getWorldManager().getBlockAt(session, blockPos); - if (blockId == BlockStateValues.JAVA_AIR_ID) { + if (blockId == Block.JAVA_AIR_ID) { continue; } if (BlockStateValues.canPistonMoveBlock(blockId, action == PistonValueType.PUSHING)) { @@ -278,7 +279,7 @@ public class PistonBlockEntity { continue; } int adjacentBlockId = session.getGeyser().getWorldManager().getBlockAt(session, adjacentPos); - if (adjacentBlockId != BlockStateValues.JAVA_AIR_ID && BlockStateValues.isBlockAttached(blockId, adjacentBlockId) && BlockStateValues.canPistonMoveBlock(adjacentBlockId, false)) { + if (adjacentBlockId != Block.JAVA_AIR_ID && BlockStateValues.isBlockAttached(blockId, adjacentBlockId) && BlockStateValues.canPistonMoveBlock(adjacentBlockId, false)) { // If it is another slime/honey block we need to check its adjacent blocks if (BlockStateValues.isBlockSticky(adjacentBlockId)) { blocksToCheck.add(adjacentPos); @@ -322,7 +323,7 @@ public class PistonBlockEntity { */ private void removeBlocks() { for (Vector3i blockPos : attachedBlocks.keySet()) { - ChunkUtils.updateBlock(session, BlockStateValues.JAVA_AIR_ID, blockPos); + ChunkUtils.updateBlock(session, Block.JAVA_AIR_ID, blockPos); } if (action != PistonValueType.PUSHING) { removePistonHead(); @@ -560,7 +561,7 @@ public class PistonBlockEntity { if (blockPos.equals(getPistonHeadPos())) { return BlockStateValues.getPistonHead(orientation); } else { - return attachedBlocks.getOrDefault(blockPos, BlockStateValues.JAVA_AIR_ID); + return attachedBlocks.getOrDefault(blockPos, Block.JAVA_AIR_ID); } } 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 ba2ddd815..e6d19e492 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 @@ -28,7 +28,8 @@ 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; +import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.inventory.ShulkerInventoryTranslator; import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @@ -40,12 +41,7 @@ public class ShulkerBoxBlockEntityTranslator extends BlockEntityTranslator imple * where {@code tag} is passed as null. */ @Override - 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; - } - bedrockNbt.putByte("facing", direction); + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, BlockState blockState) { + bedrockNbt.putByte("facing", (byte) blockState.getValue(Properties.FACING).ordinal()); } } 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 bbf0dbcb3..2a1ccb639 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 @@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.level.block.entity; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.translator.text.MessageTranslator; @@ -73,7 +74,7 @@ public class SignBlockEntityTranslator extends BlockEntityTranslator { } @Override - public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) { bedrockNbt.putCompound("FrontText", translateSide(javaNbt.getCompound("front_text"))); bedrockNbt.putCompound("BackText", translateSide(javaNbt.getCompound("back_text"))); bedrockNbt.putBoolean("IsWaxed", javaNbt.getBoolean("is_waxed")); 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 b1ab017e8..c03ae8ef0 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 @@ -34,6 +34,8 @@ import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.SkullCache; import org.geysermc.geyser.skin.SkinProvider; @@ -50,16 +52,19 @@ import java.util.concurrent.ExecutionException; public class SkullBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { @Override - public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { - byte skullVariant = BlockStateValues.getSkullVariant(blockState); - float rotation = BlockStateValues.getSkullRotation(blockState) * 22.5f; + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) { + byte skullVariant = BlockStateValues.getSkullVariant(blockState.javaId()); // TODO // Just in case... if (skullVariant == -1) { skullVariant = 0; } - bedrockNbt.putFloat("Rotation", rotation); + Integer rotation = blockState.getValue(Properties.ROTATION_16); + if (rotation != null) { + // Could be a wall skull block + bedrockNbt.putFloat("Rotation", rotation * 22.5f); + } bedrockNbt.putByte("SkullType", skullVariant); - if (BlockStateValues.isSkullPowered(blockState)) { + if (blockState.getValue(Properties.POWERED)) { bedrockNbt.putBoolean("MouthMoving", true); } } 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 edf71d384..4b6a630ba 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 @@ -32,6 +32,7 @@ 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.level.block.type.BlockState; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @@ -40,7 +41,7 @@ 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, @Nullable NbtMap javaNbt, int blockState) { + public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, @Nullable NbtMap javaNbt, BlockState blockState) { if (javaNbt == null) { return super.getBlockEntityTag(session, type, x, y, z, javaNbt, blockState); } @@ -70,7 +71,7 @@ public class SpawnerBlockEntityTranslator extends BlockEntityTranslator { } @Override - public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) { Object current; // TODO use primitive get and put methods 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 4bb9c5676..79fb3da6b 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 @@ -32,6 +32,7 @@ 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.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.StructureBlockUtils; import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @@ -40,7 +41,7 @@ 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, @Nullable NbtMap javaNbt, int blockState) { + public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, @Nullable NbtMap javaNbt, BlockState blockState) { if (javaNbt == null) { return super.getBlockEntityTag(session, type, x, y, z, javaNbt, blockState); } @@ -73,7 +74,7 @@ public class StructureBlockBlockEntityTranslator extends BlockEntityTranslator { } @Override - public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) { if (javaNbt.size() < 5) { return; // These values aren't here } 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 ff3f89f3f..a4c158a15 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 @@ -27,6 +27,7 @@ package org.geysermc.geyser.translator.level.block.entity; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @@ -34,7 +35,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType public class TrialSpawnerBlockEntityTranslator extends BlockEntityTranslator { @Override - public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) { + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) { if (javaNbt == null) { return; } 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 35c46ffd2..9cb3fb455 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,6 +25,7 @@ package org.geysermc.geyser.translator.protocol.bedrock; +import org.geysermc.geyser.level.block.type.Block; import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.packet.BlockPickRequestPacket; @@ -48,7 +49,7 @@ public class BedrockBlockPickRequestTranslator extends PacketTranslator> 4) - yOffset]; - int blockState = section.get(x, y & 0xF, z); + BlockState blockState = BlockRegistries.BLOCK_STATES.get(section.get(x, y & 0xF, z)); - if (type == BlockEntityType.LECTERN && BlockStateValues.getLecternBookStates().get(blockState)) { + if (type == BlockEntityType.LECTERN && blockState.getValue(Properties.HAS_BOOK)) { // If getLecternBookStates is false, let's just treat it like a normal block entity // Fill in tag with a default value NbtMapBuilder lecternTag = LecternUtils.getBaseLecternTag(x + chunkBlockX, y, z + chunkBlockZ, 1); @@ -419,7 +422,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator> 4) - (bedrockDimension.minY() >> 4); int subChunkIndex = (y >> 4) + (bedrockDimension.minY() >> 4); 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 379162540..a1e956ace 100644 --- a/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java @@ -41,6 +41,8 @@ import org.geysermc.geyser.entity.type.ItemFrameEntity; import org.geysermc.geyser.level.BedrockDimension; import org.geysermc.geyser.level.JavaDimension; import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.type.Block; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.level.chunk.BlockStorage; import org.geysermc.geyser.level.chunk.GeyserChunkSection; import org.geysermc.geyser.level.chunk.bitarray.SingletonBitArray; @@ -50,8 +52,6 @@ import org.geysermc.geyser.session.cache.SkullCache; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.translator.level.block.entity.BedrockOnlyBlockEntity; -import static org.geysermc.geyser.level.block.BlockStateValues.JAVA_AIR_ID; - @UtilityClass public class ChunkUtils { @@ -130,7 +130,7 @@ public class ChunkUtils { // Checks for item frames so they aren't tripped up and removed ItemFrameEntity itemFrameEntity = ItemFrameEntity.getItemFrameEntity(session, position); if (itemFrameEntity != null) { - if (blockState == JAVA_AIR_ID) { // Item frame is still present and no block overrides that; refresh it + if (blockState == Block.JAVA_AIR_ID) { // Item frame is still present and no block overrides that; refresh it itemFrameEntity.updateBlock(true); // Still update the chunk cache with the new block if updateBlock is called return; @@ -180,21 +180,21 @@ public class ChunkUtils { BlockDefinition aboveBedrockExtendedCollisionDefinition = session.getBlockMappings().getExtendedCollisionBoxes().get(blockState); int belowBlock = session.getGeyser().getWorldManager().getBlockAt(session, position.getX(), position.getY() - 1, position.getZ()); BlockDefinition belowBedrockExtendedCollisionDefinition = session.getBlockMappings().getExtendedCollisionBoxes().get(belowBlock); - if (belowBedrockExtendedCollisionDefinition != null && blockState == BlockStateValues.JAVA_AIR_ID) { + if (belowBedrockExtendedCollisionDefinition != null && blockState == Block.JAVA_AIR_ID) { UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); updateBlockPacket.setDataLayer(0); updateBlockPacket.setBlockPosition(position); updateBlockPacket.setDefinition(belowBedrockExtendedCollisionDefinition); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); session.sendUpstreamPacket(updateBlockPacket); - } else if (aboveBedrockExtendedCollisionDefinition != null && aboveBlock == BlockStateValues.JAVA_AIR_ID) { + } else if (aboveBedrockExtendedCollisionDefinition != null && aboveBlock == Block.JAVA_AIR_ID) { UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); updateBlockPacket.setDataLayer(0); updateBlockPacket.setBlockPosition(position.add(0, 1, 0)); updateBlockPacket.setDefinition(aboveBedrockExtendedCollisionDefinition); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); session.sendUpstreamPacket(updateBlockPacket); - } else if (aboveBlock == BlockStateValues.JAVA_AIR_ID) { + } else if (aboveBlock == Block.JAVA_AIR_ID) { UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); updateBlockPacket.setDataLayer(0); updateBlockPacket.setBlockPosition(position.add(0, 1, 0)); @@ -211,7 +211,7 @@ public class ChunkUtils { for (BedrockOnlyBlockEntity bedrockOnlyBlockEntity : BlockEntityUtils.BEDROCK_ONLY_BLOCK_ENTITIES) { if (bedrockOnlyBlockEntity.isBlock(blockState)) { // Flower pots are block entities only in Bedrock and are not updated anywhere else like note blocks - bedrockOnlyBlockEntity.updateBlock(session, blockState, position); + bedrockOnlyBlockEntity.updateBlock(session, BlockState.of(blockState), position); //TODO blockState break; //No block will be a part of two classes } } 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 85f8fc704..7559347e9 100644 --- a/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java @@ -34,6 +34,7 @@ import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket; import org.cloudburstmc.protocol.bedrock.packet.PlaySoundPacket; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.SoundMapping; @@ -147,7 +148,7 @@ public final class SoundUtils { soundPacket.setExtraData(soundMapping.getExtraData() + (int)(Math.round((Math.log10(pitch) / Math.log10(2)) * 12)) + 12); } else if (sound == SoundEvent.PLACE && soundMapping.getExtraData() == -1) { if (!soundMapping.getIdentifier().equals(":")) { - int javaId = BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getOrDefault(soundMapping.getIdentifier(), BlockStateValues.JAVA_AIR_ID); + int javaId = BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getOrDefault(soundMapping.getIdentifier(), Block.JAVA_AIR_ID); soundPacket.setExtraData(session.getBlockMappings().getBedrockBlockId(javaId)); } else { session.getGeyser().getLogger().debug("PLACE sound mapping identifier was invalid! Please report: " + soundMapping); 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 96328bcdd..8f9be0b98 100644 --- a/core/src/main/java/org/geysermc/geyser/util/StatisticsUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/StatisticsUtils.java @@ -29,6 +29,7 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap; import org.geysermc.cumulus.form.SimpleForm; import org.geysermc.cumulus.util.FormImage; import org.geysermc.geyser.item.type.Item; +import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.session.GeyserSession; @@ -93,10 +94,10 @@ public class StatisticsUtils { for (Object2IntMap.Entry entry : session.getStatistics().object2IntEntrySet()) { if (entry.getKey() instanceof BreakBlockStatistic statistic) { - String identifier = BlockRegistries.CLEAN_JAVA_IDENTIFIERS.get(statistic.getId()); - if (identifier != null) { - String block = identifier.replace("minecraft:", "block.minecraft."); - content.add(block + ": " + entry.getIntValue()); + Block block = BlockRegistries.JAVA_BLOCKS_TO_RENAME.get(statistic.getId()); + if (block != null) { + String identifier = block.javaIdentifier().replace("minecraft:", "block.minecraft."); + content.add(identifier + ": " + entry.getIntValue()); } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0500a31be..0f0845137 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -65,6 +65,7 @@ fastutil-int-byte-maps = { group = "com.nukkitx.fastutil", name = "fastutil-int- fastutil-int-boolean-maps = { group = "com.nukkitx.fastutil", name = "fastutil-int-boolean-maps", version.ref = "fastutil" } fastutil-object-int-maps = { group = "com.nukkitx.fastutil", name = "fastutil-object-int-maps", version.ref = "fastutil" } fastutil-object-object-maps = { group = "com.nukkitx.fastutil", name = "fastutil-object-object-maps", version.ref = "fastutil" } +fastutil-reference-object-maps = { group = "com.nukkitx.fastutil", name = "fastutil-reference-object-maps", version.ref = "fastutil" } adventure-text-serializer-gson = { group = "net.kyori", name = "adventure-text-serializer-gson", version.ref = "adventure" } # Remove when we remove our Adventure bump adventure-text-serializer-legacy = { group = "net.kyori", name = "adventure-text-serializer-legacy", version.ref = "adventure" } @@ -142,7 +143,7 @@ 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" ] +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", "fastutil-reference-object-maps" ] adventure = [ "adventure-text-serializer-gson", "adventure-text-serializer-legacy", "adventure-text-serializer-plain" ] log4j = [ "log4j-api", "log4j-core", "log4j-slf4j2-impl" ] jline = [ "jline-terminal", "jline-terminal-jna", "jline-reader" ] From a46332ace19aadf2d09f258f7c9ef456cf0af965 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Fri, 17 May 2024 14:50:21 -0400 Subject: [PATCH 010/233] Move block breaking to new system --- .../geysermc/geyser/level/block/Blocks.java | 1834 ++++++++--------- .../geyser/level/block/type/Block.java | 36 + .../populator/BlockRegistryPopulator.java | 10 + .../geyser/session/cache/TagCache.java | 14 +- .../player/BedrockActionTranslator.java | 5 +- .../level/JavaBlockDestructionTranslator.java | 7 +- .../org/geysermc/geyser/util/BlockUtils.java | 44 +- 7 files changed, 1005 insertions(+), 945 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java index 426895269..1f9c9c162 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java @@ -38,30 +38,30 @@ import static org.geysermc.geyser.level.block.type.Block.builder; @SuppressWarnings("unused") public final class Blocks { public static final Block AIR = register(new Block("air", builder())); - public static final Block STONE = register(new Block("stone", builder())); - public static final Block GRANITE = register(new Block("granite", builder())); - public static final Block POLISHED_GRANITE = register(new Block("polished_granite", builder())); - public static final Block DIORITE = register(new Block("diorite", builder())); - public static final Block POLISHED_DIORITE = register(new Block("polished_diorite", builder())); - public static final Block ANDESITE = register(new Block("andesite", builder())); - public static final Block POLISHED_ANDESITE = register(new Block("polished_andesite", builder())); - public static final Block GRASS_BLOCK = register(new Block("grass_block", builder() + public static final Block STONE = register(new Block("stone", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block GRANITE = register(new Block("granite", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block POLISHED_GRANITE = register(new Block("polished_granite", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block DIORITE = register(new Block("diorite", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block POLISHED_DIORITE = register(new Block("polished_diorite", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block ANDESITE = register(new Block("andesite", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block POLISHED_ANDESITE = register(new Block("polished_andesite", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block GRASS_BLOCK = register(new Block("grass_block", builder().destroyTime(0.6f) .booleanState(SNOWY))); - public static final Block DIRT = register(new Block("dirt", builder())); - public static final Block COARSE_DIRT = register(new Block("coarse_dirt", builder())); - public static final Block PODZOL = register(new Block("podzol", builder() + public static final Block DIRT = register(new Block("dirt", builder().destroyTime(0.5f))); + public static final Block COARSE_DIRT = register(new Block("coarse_dirt", builder().destroyTime(0.5f))); + public static final Block PODZOL = register(new Block("podzol", builder().destroyTime(0.5f) .booleanState(SNOWY))); - public static final Block COBBLESTONE = register(new Block("cobblestone", builder())); - public static final Block OAK_PLANKS = register(new Block("oak_planks", builder())); - public static final Block SPRUCE_PLANKS = register(new Block("spruce_planks", builder())); - public static final Block BIRCH_PLANKS = register(new Block("birch_planks", builder())); - public static final Block JUNGLE_PLANKS = register(new Block("jungle_planks", builder())); - public static final Block ACACIA_PLANKS = register(new Block("acacia_planks", builder())); - public static final Block CHERRY_PLANKS = register(new Block("cherry_planks", builder())); - public static final Block DARK_OAK_PLANKS = register(new Block("dark_oak_planks", builder())); - public static final Block MANGROVE_PLANKS = register(new Block("mangrove_planks", builder())); - public static final Block BAMBOO_PLANKS = register(new Block("bamboo_planks", builder())); - public static final Block BAMBOO_MOSAIC = register(new Block("bamboo_mosaic", builder())); + public static final Block COBBLESTONE = register(new Block("cobblestone", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); + public static final Block OAK_PLANKS = register(new Block("oak_planks", builder().destroyTime(2.0f))); + public static final Block SPRUCE_PLANKS = register(new Block("spruce_planks", builder().destroyTime(2.0f))); + public static final Block BIRCH_PLANKS = register(new Block("birch_planks", builder().destroyTime(2.0f))); + public static final Block JUNGLE_PLANKS = register(new Block("jungle_planks", builder().destroyTime(2.0f))); + public static final Block ACACIA_PLANKS = register(new Block("acacia_planks", builder().destroyTime(2.0f))); + public static final Block CHERRY_PLANKS = register(new Block("cherry_planks", builder().destroyTime(2.0f))); + public static final Block DARK_OAK_PLANKS = register(new Block("dark_oak_planks", builder().destroyTime(2.0f))); + public static final Block MANGROVE_PLANKS = register(new Block("mangrove_planks", builder().destroyTime(2.0f))); + public static final Block BAMBOO_PLANKS = register(new Block("bamboo_planks", builder().destroyTime(2.0f))); + public static final Block BAMBOO_MOSAIC = register(new Block("bamboo_mosaic", builder().destroyTime(2.0f))); public static final Block OAK_SAPLING = register(new Block("oak_sapling", builder() .intState(STAGE, 0, 1))); public static final Block SPRUCE_SAPLING = register(new Block("spruce_sapling", builder() @@ -81,259 +81,259 @@ public final class Blocks { .booleanState(HANGING) .intState(STAGE, 0, 1) .booleanState(WATERLOGGED))); - public static final Block BEDROCK = register(new Block("bedrock", builder())); - public static final Block WATER = register(new Block("water", builder() + public static final Block BEDROCK = register(new Block("bedrock", builder().destroyTime(-1.0f))); + public static final Block WATER = register(new Block("water", builder().destroyTime(100.0f) .intState(LEVEL, 0, 15))); - public static final Block LAVA = register(new Block("lava", builder() + public static final Block LAVA = register(new Block("lava", builder().destroyTime(100.0f) .intState(LEVEL, 0, 15))); - public static final Block SAND = register(new Block("sand", builder())); - public static final Block SUSPICIOUS_SAND = register(new Block("suspicious_sand", builder() + public static final Block SAND = register(new Block("sand", builder().destroyTime(0.5f))); + public static final Block SUSPICIOUS_SAND = register(new Block("suspicious_sand", builder().setBlockEntity().destroyTime(0.25f) .intState(DUSTED, 0, 3))); - public static final Block RED_SAND = register(new Block("red_sand", builder())); - public static final Block GRAVEL = register(new Block("gravel", builder())); - public static final Block SUSPICIOUS_GRAVEL = register(new Block("suspicious_gravel", builder() + public static final Block RED_SAND = register(new Block("red_sand", builder().destroyTime(0.5f))); + public static final Block GRAVEL = register(new Block("gravel", builder().destroyTime(0.6f))); + public static final Block SUSPICIOUS_GRAVEL = register(new Block("suspicious_gravel", builder().setBlockEntity().destroyTime(0.25f) .intState(DUSTED, 0, 3))); - public static final Block GOLD_ORE = register(new Block("gold_ore", builder())); - public static final Block DEEPSLATE_GOLD_ORE = register(new Block("deepslate_gold_ore", builder())); - public static final Block IRON_ORE = register(new Block("iron_ore", builder())); - public static final Block DEEPSLATE_IRON_ORE = register(new Block("deepslate_iron_ore", builder())); - public static final Block COAL_ORE = register(new Block("coal_ore", builder())); - public static final Block DEEPSLATE_COAL_ORE = register(new Block("deepslate_coal_ore", builder())); - public static final Block NETHER_GOLD_ORE = register(new Block("nether_gold_ore", builder())); - public static final Block OAK_LOG = register(new Block("oak_log", builder() + public static final Block GOLD_ORE = register(new Block("gold_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block DEEPSLATE_GOLD_ORE = register(new Block("deepslate_gold_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f))); + public static final Block IRON_ORE = register(new Block("iron_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block DEEPSLATE_IRON_ORE = register(new Block("deepslate_iron_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f))); + public static final Block COAL_ORE = register(new Block("coal_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block DEEPSLATE_COAL_ORE = register(new Block("deepslate_coal_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f))); + public static final Block NETHER_GOLD_ORE = register(new Block("nether_gold_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block OAK_LOG = register(new Block("oak_log", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block SPRUCE_LOG = register(new Block("spruce_log", builder() + public static final Block SPRUCE_LOG = register(new Block("spruce_log", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block BIRCH_LOG = register(new Block("birch_log", builder() + public static final Block BIRCH_LOG = register(new Block("birch_log", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block JUNGLE_LOG = register(new Block("jungle_log", builder() + public static final Block JUNGLE_LOG = register(new Block("jungle_log", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block ACACIA_LOG = register(new Block("acacia_log", builder() + public static final Block ACACIA_LOG = register(new Block("acacia_log", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block CHERRY_LOG = register(new Block("cherry_log", builder() + public static final Block CHERRY_LOG = register(new Block("cherry_log", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block DARK_OAK_LOG = register(new Block("dark_oak_log", builder() + public static final Block DARK_OAK_LOG = register(new Block("dark_oak_log", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block MANGROVE_LOG = register(new Block("mangrove_log", builder() + public static final Block MANGROVE_LOG = register(new Block("mangrove_log", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block MANGROVE_ROOTS = register(new Block("mangrove_roots", builder() + public static final Block MANGROVE_ROOTS = register(new Block("mangrove_roots", builder().destroyTime(0.7f) .booleanState(WATERLOGGED))); - public static final Block MUDDY_MANGROVE_ROOTS = register(new Block("muddy_mangrove_roots", builder() + public static final Block MUDDY_MANGROVE_ROOTS = register(new Block("muddy_mangrove_roots", builder().destroyTime(0.7f) .enumState(AXIS, Axis.VALUES))); - public static final Block BAMBOO_BLOCK = register(new Block("bamboo_block", builder() + public static final Block BAMBOO_BLOCK = register(new Block("bamboo_block", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block STRIPPED_SPRUCE_LOG = register(new Block("stripped_spruce_log", builder() + public static final Block STRIPPED_SPRUCE_LOG = register(new Block("stripped_spruce_log", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block STRIPPED_BIRCH_LOG = register(new Block("stripped_birch_log", builder() + public static final Block STRIPPED_BIRCH_LOG = register(new Block("stripped_birch_log", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block STRIPPED_JUNGLE_LOG = register(new Block("stripped_jungle_log", builder() + public static final Block STRIPPED_JUNGLE_LOG = register(new Block("stripped_jungle_log", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block STRIPPED_ACACIA_LOG = register(new Block("stripped_acacia_log", builder() + public static final Block STRIPPED_ACACIA_LOG = register(new Block("stripped_acacia_log", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block STRIPPED_CHERRY_LOG = register(new Block("stripped_cherry_log", builder() + public static final Block STRIPPED_CHERRY_LOG = register(new Block("stripped_cherry_log", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block STRIPPED_DARK_OAK_LOG = register(new Block("stripped_dark_oak_log", builder() + public static final Block STRIPPED_DARK_OAK_LOG = register(new Block("stripped_dark_oak_log", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block STRIPPED_OAK_LOG = register(new Block("stripped_oak_log", builder() + public static final Block STRIPPED_OAK_LOG = register(new Block("stripped_oak_log", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block STRIPPED_MANGROVE_LOG = register(new Block("stripped_mangrove_log", builder() + public static final Block STRIPPED_MANGROVE_LOG = register(new Block("stripped_mangrove_log", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block STRIPPED_BAMBOO_BLOCK = register(new Block("stripped_bamboo_block", builder() + public static final Block STRIPPED_BAMBOO_BLOCK = register(new Block("stripped_bamboo_block", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block OAK_WOOD = register(new Block("oak_wood", builder() + public static final Block OAK_WOOD = register(new Block("oak_wood", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block SPRUCE_WOOD = register(new Block("spruce_wood", builder() + public static final Block SPRUCE_WOOD = register(new Block("spruce_wood", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block BIRCH_WOOD = register(new Block("birch_wood", builder() + public static final Block BIRCH_WOOD = register(new Block("birch_wood", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block JUNGLE_WOOD = register(new Block("jungle_wood", builder() + public static final Block JUNGLE_WOOD = register(new Block("jungle_wood", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block ACACIA_WOOD = register(new Block("acacia_wood", builder() + public static final Block ACACIA_WOOD = register(new Block("acacia_wood", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block CHERRY_WOOD = register(new Block("cherry_wood", builder() + public static final Block CHERRY_WOOD = register(new Block("cherry_wood", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block DARK_OAK_WOOD = register(new Block("dark_oak_wood", builder() + public static final Block DARK_OAK_WOOD = register(new Block("dark_oak_wood", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block MANGROVE_WOOD = register(new Block("mangrove_wood", builder() + public static final Block MANGROVE_WOOD = register(new Block("mangrove_wood", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block STRIPPED_OAK_WOOD = register(new Block("stripped_oak_wood", builder() + public static final Block STRIPPED_OAK_WOOD = register(new Block("stripped_oak_wood", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block STRIPPED_SPRUCE_WOOD = register(new Block("stripped_spruce_wood", builder() + public static final Block STRIPPED_SPRUCE_WOOD = register(new Block("stripped_spruce_wood", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block STRIPPED_BIRCH_WOOD = register(new Block("stripped_birch_wood", builder() + public static final Block STRIPPED_BIRCH_WOOD = register(new Block("stripped_birch_wood", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block STRIPPED_JUNGLE_WOOD = register(new Block("stripped_jungle_wood", builder() + public static final Block STRIPPED_JUNGLE_WOOD = register(new Block("stripped_jungle_wood", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block STRIPPED_ACACIA_WOOD = register(new Block("stripped_acacia_wood", builder() + public static final Block STRIPPED_ACACIA_WOOD = register(new Block("stripped_acacia_wood", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block STRIPPED_CHERRY_WOOD = register(new Block("stripped_cherry_wood", builder() + public static final Block STRIPPED_CHERRY_WOOD = register(new Block("stripped_cherry_wood", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block STRIPPED_DARK_OAK_WOOD = register(new Block("stripped_dark_oak_wood", builder() + public static final Block STRIPPED_DARK_OAK_WOOD = register(new Block("stripped_dark_oak_wood", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block STRIPPED_MANGROVE_WOOD = register(new Block("stripped_mangrove_wood", builder() + public static final Block STRIPPED_MANGROVE_WOOD = register(new Block("stripped_mangrove_wood", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block OAK_LEAVES = register(new Block("oak_leaves", builder() + public static final Block OAK_LEAVES = register(new Block("oak_leaves", builder().destroyTime(0.2f) .intState(DISTANCE, 1, 7) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); - public static final Block SPRUCE_LEAVES = register(new Block("spruce_leaves", builder() + public static final Block SPRUCE_LEAVES = register(new Block("spruce_leaves", builder().destroyTime(0.2f) .intState(DISTANCE, 1, 7) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); - public static final Block BIRCH_LEAVES = register(new Block("birch_leaves", builder() + public static final Block BIRCH_LEAVES = register(new Block("birch_leaves", builder().destroyTime(0.2f) .intState(DISTANCE, 1, 7) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); - public static final Block JUNGLE_LEAVES = register(new Block("jungle_leaves", builder() + public static final Block JUNGLE_LEAVES = register(new Block("jungle_leaves", builder().destroyTime(0.2f) .intState(DISTANCE, 1, 7) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); - public static final Block ACACIA_LEAVES = register(new Block("acacia_leaves", builder() + public static final Block ACACIA_LEAVES = register(new Block("acacia_leaves", builder().destroyTime(0.2f) .intState(DISTANCE, 1, 7) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); - public static final Block CHERRY_LEAVES = register(new Block("cherry_leaves", builder() + public static final Block CHERRY_LEAVES = register(new Block("cherry_leaves", builder().destroyTime(0.2f) .intState(DISTANCE, 1, 7) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); - public static final Block DARK_OAK_LEAVES = register(new Block("dark_oak_leaves", builder() + public static final Block DARK_OAK_LEAVES = register(new Block("dark_oak_leaves", builder().destroyTime(0.2f) .intState(DISTANCE, 1, 7) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); - public static final Block MANGROVE_LEAVES = register(new Block("mangrove_leaves", builder() + public static final Block MANGROVE_LEAVES = register(new Block("mangrove_leaves", builder().destroyTime(0.2f) .intState(DISTANCE, 1, 7) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); - public static final Block AZALEA_LEAVES = register(new Block("azalea_leaves", builder() + public static final Block AZALEA_LEAVES = register(new Block("azalea_leaves", builder().destroyTime(0.2f) .intState(DISTANCE, 1, 7) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); - public static final Block FLOWERING_AZALEA_LEAVES = register(new Block("flowering_azalea_leaves", builder() + public static final Block FLOWERING_AZALEA_LEAVES = register(new Block("flowering_azalea_leaves", builder().destroyTime(0.2f) .intState(DISTANCE, 1, 7) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); - public static final Block SPONGE = register(new Block("sponge", builder())); - public static final Block WET_SPONGE = register(new Block("wet_sponge", builder())); - public static final Block GLASS = register(new Block("glass", builder())); - public static final Block LAPIS_ORE = register(new Block("lapis_ore", builder())); - public static final Block DEEPSLATE_LAPIS_ORE = register(new Block("deepslate_lapis_ore", builder())); - public static final Block LAPIS_BLOCK = register(new Block("lapis_block", builder())); - public static final Block DISPENSER = register(new Block("dispenser", builder() + public static final Block SPONGE = register(new Block("sponge", builder().destroyTime(0.6f))); + public static final Block WET_SPONGE = register(new Block("wet_sponge", builder().destroyTime(0.6f))); + public static final Block GLASS = register(new Block("glass", builder().destroyTime(0.3f))); + public static final Block LAPIS_ORE = register(new Block("lapis_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block DEEPSLATE_LAPIS_ORE = register(new Block("deepslate_lapis_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f))); + public static final Block LAPIS_BLOCK = register(new Block("lapis_block", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block DISPENSER = register(new Block("dispenser", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .booleanState(TRIGGERED))); - public static final Block SANDSTONE = register(new Block("sandstone", builder())); - public static final Block CHISELED_SANDSTONE = register(new Block("chiseled_sandstone", builder())); - public static final Block CUT_SANDSTONE = register(new Block("cut_sandstone", builder())); - public static final Block NOTE_BLOCK = register(new Block("note_block", builder() + public static final Block SANDSTONE = register(new Block("sandstone", builder().requiresCorrectToolForDrops().destroyTime(0.8f))); + public static final Block CHISELED_SANDSTONE = register(new Block("chiseled_sandstone", builder().requiresCorrectToolForDrops().destroyTime(0.8f))); + public static final Block CUT_SANDSTONE = register(new Block("cut_sandstone", builder().requiresCorrectToolForDrops().destroyTime(0.8f))); + public static final Block NOTE_BLOCK = register(new Block("note_block", builder().destroyTime(0.8f) .enumState(NOTEBLOCK_INSTRUMENT, "harp", "basedrum", "snare", "hat", "bass", "flute", "bell", "guitar", "chime", "xylophone", "iron_xylophone", "cow_bell", "didgeridoo", "bit", "banjo", "pling", "zombie", "skeleton", "creeper", "dragon", "wither_skeleton", "piglin", "custom_head") .intState(NOTE, 0, 24) .booleanState(POWERED))); - public static final Block WHITE_BED = register(new BedBlock("white_bed", 0, builder() + public static final Block WHITE_BED = register(new BedBlock("white_bed", 0, builder().setBlockEntity().destroyTime(0.2f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block ORANGE_BED = register(new BedBlock("orange_bed", 1, builder() + public static final Block ORANGE_BED = register(new BedBlock("orange_bed", 1, builder().setBlockEntity().destroyTime(0.2f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block MAGENTA_BED = register(new BedBlock("magenta_bed", 2, builder() + public static final Block MAGENTA_BED = register(new BedBlock("magenta_bed", 2, builder().setBlockEntity().destroyTime(0.2f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block LIGHT_BLUE_BED = register(new BedBlock("light_blue_bed", 3, builder() + public static final Block LIGHT_BLUE_BED = register(new BedBlock("light_blue_bed", 3, builder().setBlockEntity().destroyTime(0.2f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block YELLOW_BED = register(new BedBlock("yellow_bed", 4, builder() + public static final Block YELLOW_BED = register(new BedBlock("yellow_bed", 4, builder().setBlockEntity().destroyTime(0.2f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block LIME_BED = register(new BedBlock("lime_bed", 5, builder() + public static final Block LIME_BED = register(new BedBlock("lime_bed", 5, builder().setBlockEntity().destroyTime(0.2f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block PINK_BED = register(new BedBlock("pink_bed", 6, builder() + public static final Block PINK_BED = register(new BedBlock("pink_bed", 6, builder().setBlockEntity().destroyTime(0.2f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block GRAY_BED = register(new BedBlock("gray_bed", 7, builder() + public static final Block GRAY_BED = register(new BedBlock("gray_bed", 7, builder().setBlockEntity().destroyTime(0.2f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block LIGHT_GRAY_BED = register(new BedBlock("light_gray_bed", 8, builder() + public static final Block LIGHT_GRAY_BED = register(new BedBlock("light_gray_bed", 8, builder().setBlockEntity().destroyTime(0.2f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block CYAN_BED = register(new BedBlock("cyan_bed", 9, builder() + public static final Block CYAN_BED = register(new BedBlock("cyan_bed", 9, builder().setBlockEntity().destroyTime(0.2f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block PURPLE_BED = register(new BedBlock("purple_bed", 10, builder() + public static final Block PURPLE_BED = register(new BedBlock("purple_bed", 10, builder().setBlockEntity().destroyTime(0.2f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block BLUE_BED = register(new BedBlock("blue_bed", 11, builder() + public static final Block BLUE_BED = register(new BedBlock("blue_bed", 11, builder().setBlockEntity().destroyTime(0.2f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block BROWN_BED = register(new BedBlock("brown_bed", 12, builder() + public static final Block BROWN_BED = register(new BedBlock("brown_bed", 12, builder().setBlockEntity().destroyTime(0.2f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block GREEN_BED = register(new BedBlock("green_bed", 13, builder() + public static final Block GREEN_BED = register(new BedBlock("green_bed", 13, builder().setBlockEntity().destroyTime(0.2f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block RED_BED = register(new BedBlock("red_bed", 14, builder() + public static final Block RED_BED = register(new BedBlock("red_bed", 14, builder().setBlockEntity().destroyTime(0.2f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block BLACK_BED = register(new BedBlock("black_bed", 15, builder() + public static final Block BLACK_BED = register(new BedBlock("black_bed", 15, builder().setBlockEntity().destroyTime(0.2f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block POWERED_RAIL = register(new Block("powered_rail", builder() + public static final Block POWERED_RAIL = register(new Block("powered_rail", builder().destroyTime(0.7f) .booleanState(POWERED) .enumState(RAIL_SHAPE_STRAIGHT, "north_south", "east_west", "ascending_east", "ascending_west", "ascending_north", "ascending_south") .booleanState(WATERLOGGED))); - public static final Block DETECTOR_RAIL = register(new Block("detector_rail", builder() + public static final Block DETECTOR_RAIL = register(new Block("detector_rail", builder().destroyTime(0.7f) .booleanState(POWERED) .enumState(RAIL_SHAPE_STRAIGHT, "north_south", "east_west", "ascending_east", "ascending_west", "ascending_north", "ascending_south") .booleanState(WATERLOGGED))); - public static final Block STICKY_PISTON = register(new Block("sticky_piston", builder() + public static final Block STICKY_PISTON = register(new Block("sticky_piston", builder().destroyTime(1.5f) .booleanState(EXTENDED) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block COBWEB = register(new Block("cobweb", builder())); + public static final Block COBWEB = register(new Block("cobweb", builder().requiresCorrectToolForDrops().destroyTime(4.0f))); public static final Block SHORT_GRASS = register(new Block("short_grass", builder())); public static final Block FERN = register(new Block("fern", builder())); public static final Block DEAD_BUSH = register(new Block("dead_bush", builder())); public static final Block SEAGRASS = register(new Block("seagrass", builder())); public static final Block TALL_SEAGRASS = register(new Block("tall_seagrass", builder() .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); - public static final Block PISTON = register(new Block("piston", builder() + public static final Block PISTON = register(new Block("piston", builder().destroyTime(1.5f) .booleanState(EXTENDED) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block PISTON_HEAD = register(new Block("piston_head", builder() + public static final Block PISTON_HEAD = register(new Block("piston_head", builder().destroyTime(1.5f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .booleanState(SHORT) .enumState(PISTON_TYPE, "normal", "sticky"))); - public static final Block WHITE_WOOL = register(new Block("white_wool", builder())); - public static final Block ORANGE_WOOL = register(new Block("orange_wool", builder())); - public static final Block MAGENTA_WOOL = register(new Block("magenta_wool", builder())); - public static final Block LIGHT_BLUE_WOOL = register(new Block("light_blue_wool", builder())); - public static final Block YELLOW_WOOL = register(new Block("yellow_wool", builder())); - public static final Block LIME_WOOL = register(new Block("lime_wool", builder())); - public static final Block PINK_WOOL = register(new Block("pink_wool", builder())); - public static final Block GRAY_WOOL = register(new Block("gray_wool", builder())); - public static final Block LIGHT_GRAY_WOOL = register(new Block("light_gray_wool", builder())); - public static final Block CYAN_WOOL = register(new Block("cyan_wool", builder())); - public static final Block PURPLE_WOOL = register(new Block("purple_wool", builder())); - public static final Block BLUE_WOOL = register(new Block("blue_wool", builder())); - public static final Block BROWN_WOOL = register(new Block("brown_wool", builder())); - public static final Block GREEN_WOOL = register(new Block("green_wool", builder())); - public static final Block RED_WOOL = register(new Block("red_wool", builder())); - public static final Block BLACK_WOOL = register(new Block("black_wool", builder())); - public static final Block MOVING_PISTON = register(new Block("moving_piston", builder() + public static final Block WHITE_WOOL = register(new Block("white_wool", builder().destroyTime(0.8f))); + public static final Block ORANGE_WOOL = register(new Block("orange_wool", builder().destroyTime(0.8f))); + public static final Block MAGENTA_WOOL = register(new Block("magenta_wool", builder().destroyTime(0.8f))); + public static final Block LIGHT_BLUE_WOOL = register(new Block("light_blue_wool", builder().destroyTime(0.8f))); + public static final Block YELLOW_WOOL = register(new Block("yellow_wool", builder().destroyTime(0.8f))); + public static final Block LIME_WOOL = register(new Block("lime_wool", builder().destroyTime(0.8f))); + public static final Block PINK_WOOL = register(new Block("pink_wool", builder().destroyTime(0.8f))); + public static final Block GRAY_WOOL = register(new Block("gray_wool", builder().destroyTime(0.8f))); + public static final Block LIGHT_GRAY_WOOL = register(new Block("light_gray_wool", builder().destroyTime(0.8f))); + public static final Block CYAN_WOOL = register(new Block("cyan_wool", builder().destroyTime(0.8f))); + public static final Block PURPLE_WOOL = register(new Block("purple_wool", builder().destroyTime(0.8f))); + public static final Block BLUE_WOOL = register(new Block("blue_wool", builder().destroyTime(0.8f))); + public static final Block BROWN_WOOL = register(new Block("brown_wool", builder().destroyTime(0.8f))); + public static final Block GREEN_WOOL = register(new Block("green_wool", builder().destroyTime(0.8f))); + public static final Block RED_WOOL = register(new Block("red_wool", builder().destroyTime(0.8f))); + public static final Block BLACK_WOOL = register(new Block("black_wool", builder().destroyTime(0.8f))); + public static final Block MOVING_PISTON = register(new Block("moving_piston", builder().setBlockEntity().destroyTime(-1.0f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .enumState(PISTON_TYPE, "normal", "sticky"))); public static final Block DANDELION = register(new Block("dandelion", builder())); @@ -352,13 +352,13 @@ public final class Blocks { public static final Block LILY_OF_THE_VALLEY = register(new Block("lily_of_the_valley", builder())); public static final Block BROWN_MUSHROOM = register(new Block("brown_mushroom", builder())); public static final Block RED_MUSHROOM = register(new Block("red_mushroom", builder())); - public static final Block GOLD_BLOCK = register(new Block("gold_block", builder())); - public static final Block IRON_BLOCK = register(new Block("iron_block", builder())); - public static final Block BRICKS = register(new Block("bricks", builder())); + public static final Block GOLD_BLOCK = register(new Block("gold_block", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block IRON_BLOCK = register(new Block("iron_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f))); + public static final Block BRICKS = register(new Block("bricks", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); public static final Block TNT = register(new Block("tnt", builder() .booleanState(UNSTABLE))); - public static final Block BOOKSHELF = register(new Block("bookshelf", builder())); - public static final Block CHISELED_BOOKSHELF = register(new Block("chiseled_bookshelf", builder() + public static final Block BOOKSHELF = register(new Block("bookshelf", builder().destroyTime(1.5f))); + public static final Block CHISELED_BOOKSHELF = register(new Block("chiseled_bookshelf", builder().setBlockEntity().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(CHISELED_BOOKSHELF_SLOT_0_OCCUPIED) .booleanState(CHISELED_BOOKSHELF_SLOT_1_OCCUPIED) @@ -366,8 +366,8 @@ public final class Blocks { .booleanState(CHISELED_BOOKSHELF_SLOT_3_OCCUPIED) .booleanState(CHISELED_BOOKSHELF_SLOT_4_OCCUPIED) .booleanState(CHISELED_BOOKSHELF_SLOT_5_OCCUPIED))); - public static final Block MOSSY_COBBLESTONE = register(new Block("mossy_cobblestone", builder())); - public static final Block OBSIDIAN = register(new Block("obsidian", builder())); + public static final Block MOSSY_COBBLESTONE = register(new Block("mossy_cobblestone", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); + public static final Block OBSIDIAN = register(new Block("obsidian", builder().requiresCorrectToolForDrops().destroyTime(50.0f))); public static final Block TORCH = register(new Block("torch", builder())); public static final Block WALL_TORCH = register(new Block("wall_torch", builder() .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); @@ -379,13 +379,13 @@ public final class Blocks { .booleanState(UP) .booleanState(WEST))); public static final Block SOUL_FIRE = register(new Block("soul_fire", builder())); - public static final Block SPAWNER = register(new Block("spawner", builder())); - public static final Block OAK_STAIRS = register(new Block("oak_stairs", builder() + public static final Block SPAWNER = register(new Block("spawner", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(5.0f))); + public static final Block OAK_STAIRS = register(new Block("oak_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block CHEST = register(new Block("chest", builder() + public static final Block CHEST = register(new Block("chest", builder().setBlockEntity().destroyTime(2.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(CHEST_TYPE, "single", "left", "right") .booleanState(WATERLOGGED))); @@ -395,369 +395,369 @@ public final class Blocks { .intState(POWER, 0, 15) .enumState(SOUTH_REDSTONE, "up", "side", "none") .enumState(WEST_REDSTONE, "up", "side", "none"))); - public static final Block DIAMOND_ORE = register(new Block("diamond_ore", builder())); - public static final Block DEEPSLATE_DIAMOND_ORE = register(new Block("deepslate_diamond_ore", builder())); - public static final Block DIAMOND_BLOCK = register(new Block("diamond_block", builder())); - public static final Block CRAFTING_TABLE = register(new Block("crafting_table", builder())); + public static final Block DIAMOND_ORE = register(new Block("diamond_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block DEEPSLATE_DIAMOND_ORE = register(new Block("deepslate_diamond_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f))); + public static final Block DIAMOND_BLOCK = register(new Block("diamond_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f))); + public static final Block CRAFTING_TABLE = register(new Block("crafting_table", builder().destroyTime(2.5f))); public static final Block WHEAT = register(new Block("wheat", builder() .intState(AGE_7, 0, 7))); - public static final Block FARMLAND = register(new Block("farmland", builder() + public static final Block FARMLAND = register(new Block("farmland", builder().destroyTime(0.6f) .intState(MOISTURE, 0, 7))); - public static final Block FURNACE = register(new Block("furnace", builder() + public static final Block FURNACE = register(new Block("furnace", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(LIT))); - public static final Block OAK_SIGN = register(new Block("oak_sign", builder() + public static final Block OAK_SIGN = register(new Block("oak_sign", builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15) .booleanState(WATERLOGGED))); - public static final Block SPRUCE_SIGN = register(new Block("spruce_sign", builder() + public static final Block SPRUCE_SIGN = register(new Block("spruce_sign", builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15) .booleanState(WATERLOGGED))); - public static final Block BIRCH_SIGN = register(new Block("birch_sign", builder() + public static final Block BIRCH_SIGN = register(new Block("birch_sign", builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15) .booleanState(WATERLOGGED))); - public static final Block ACACIA_SIGN = register(new Block("acacia_sign", builder() + public static final Block ACACIA_SIGN = register(new Block("acacia_sign", builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15) .booleanState(WATERLOGGED))); - public static final Block CHERRY_SIGN = register(new Block("cherry_sign", builder() + public static final Block CHERRY_SIGN = register(new Block("cherry_sign", builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15) .booleanState(WATERLOGGED))); - public static final Block JUNGLE_SIGN = register(new Block("jungle_sign", builder() + public static final Block JUNGLE_SIGN = register(new Block("jungle_sign", builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15) .booleanState(WATERLOGGED))); - public static final Block DARK_OAK_SIGN = register(new Block("dark_oak_sign", builder() + public static final Block DARK_OAK_SIGN = register(new Block("dark_oak_sign", builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15) .booleanState(WATERLOGGED))); - public static final Block MANGROVE_SIGN = register(new Block("mangrove_sign", builder() + public static final Block MANGROVE_SIGN = register(new Block("mangrove_sign", builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15) .booleanState(WATERLOGGED))); - public static final Block BAMBOO_SIGN = register(new Block("bamboo_sign", builder() + public static final Block BAMBOO_SIGN = register(new Block("bamboo_sign", builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15) .booleanState(WATERLOGGED))); - public static final Block OAK_DOOR = register(new Block("oak_door", builder() + public static final Block OAK_DOOR = register(new Block("oak_door", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block LADDER = register(new Block("ladder", builder() + public static final Block LADDER = register(new Block("ladder", builder().destroyTime(0.4f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block RAIL = register(new Block("rail", builder() + public static final Block RAIL = register(new Block("rail", builder().destroyTime(0.7f) .enumState(RAIL_SHAPE, "north_south", "east_west", "ascending_east", "ascending_west", "ascending_north", "ascending_south", "south_east", "south_west", "north_west", "north_east") .booleanState(WATERLOGGED))); - public static final Block COBBLESTONE_STAIRS = register(new Block("cobblestone_stairs", builder() + public static final Block COBBLESTONE_STAIRS = register(new Block("cobblestone_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block OAK_WALL_SIGN = register(new Block("oak_wall_sign", builder() + public static final Block OAK_WALL_SIGN = register(new Block("oak_wall_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block SPRUCE_WALL_SIGN = register(new Block("spruce_wall_sign", builder() + public static final Block SPRUCE_WALL_SIGN = register(new Block("spruce_wall_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block BIRCH_WALL_SIGN = register(new Block("birch_wall_sign", builder() + public static final Block BIRCH_WALL_SIGN = register(new Block("birch_wall_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block ACACIA_WALL_SIGN = register(new Block("acacia_wall_sign", builder() + public static final Block ACACIA_WALL_SIGN = register(new Block("acacia_wall_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block CHERRY_WALL_SIGN = register(new Block("cherry_wall_sign", builder() + public static final Block CHERRY_WALL_SIGN = register(new Block("cherry_wall_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block JUNGLE_WALL_SIGN = register(new Block("jungle_wall_sign", builder() + public static final Block JUNGLE_WALL_SIGN = register(new Block("jungle_wall_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block DARK_OAK_WALL_SIGN = register(new Block("dark_oak_wall_sign", builder() + public static final Block DARK_OAK_WALL_SIGN = register(new Block("dark_oak_wall_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block MANGROVE_WALL_SIGN = register(new Block("mangrove_wall_sign", builder() + public static final Block MANGROVE_WALL_SIGN = register(new Block("mangrove_wall_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block BAMBOO_WALL_SIGN = register(new Block("bamboo_wall_sign", builder() + public static final Block BAMBOO_WALL_SIGN = register(new Block("bamboo_wall_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block OAK_HANGING_SIGN = register(new Block("oak_hanging_sign", builder() + public static final Block OAK_HANGING_SIGN = register(new Block("oak_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .booleanState(ATTACHED) .intState(ROTATION_16, 0, 15) .booleanState(WATERLOGGED))); - public static final Block SPRUCE_HANGING_SIGN = register(new Block("spruce_hanging_sign", builder() + public static final Block SPRUCE_HANGING_SIGN = register(new Block("spruce_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .booleanState(ATTACHED) .intState(ROTATION_16, 0, 15) .booleanState(WATERLOGGED))); - public static final Block BIRCH_HANGING_SIGN = register(new Block("birch_hanging_sign", builder() + public static final Block BIRCH_HANGING_SIGN = register(new Block("birch_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .booleanState(ATTACHED) .intState(ROTATION_16, 0, 15) .booleanState(WATERLOGGED))); - public static final Block ACACIA_HANGING_SIGN = register(new Block("acacia_hanging_sign", builder() + public static final Block ACACIA_HANGING_SIGN = register(new Block("acacia_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .booleanState(ATTACHED) .intState(ROTATION_16, 0, 15) .booleanState(WATERLOGGED))); - public static final Block CHERRY_HANGING_SIGN = register(new Block("cherry_hanging_sign", builder() + public static final Block CHERRY_HANGING_SIGN = register(new Block("cherry_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .booleanState(ATTACHED) .intState(ROTATION_16, 0, 15) .booleanState(WATERLOGGED))); - public static final Block JUNGLE_HANGING_SIGN = register(new Block("jungle_hanging_sign", builder() + public static final Block JUNGLE_HANGING_SIGN = register(new Block("jungle_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .booleanState(ATTACHED) .intState(ROTATION_16, 0, 15) .booleanState(WATERLOGGED))); - public static final Block DARK_OAK_HANGING_SIGN = register(new Block("dark_oak_hanging_sign", builder() + public static final Block DARK_OAK_HANGING_SIGN = register(new Block("dark_oak_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .booleanState(ATTACHED) .intState(ROTATION_16, 0, 15) .booleanState(WATERLOGGED))); - public static final Block CRIMSON_HANGING_SIGN = register(new Block("crimson_hanging_sign", builder() + public static final Block CRIMSON_HANGING_SIGN = register(new Block("crimson_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .booleanState(ATTACHED) .intState(ROTATION_16, 0, 15) .booleanState(WATERLOGGED))); - public static final Block WARPED_HANGING_SIGN = register(new Block("warped_hanging_sign", builder() + public static final Block WARPED_HANGING_SIGN = register(new Block("warped_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .booleanState(ATTACHED) .intState(ROTATION_16, 0, 15) .booleanState(WATERLOGGED))); - public static final Block MANGROVE_HANGING_SIGN = register(new Block("mangrove_hanging_sign", builder() + public static final Block MANGROVE_HANGING_SIGN = register(new Block("mangrove_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .booleanState(ATTACHED) .intState(ROTATION_16, 0, 15) .booleanState(WATERLOGGED))); - public static final Block BAMBOO_HANGING_SIGN = register(new Block("bamboo_hanging_sign", builder() + public static final Block BAMBOO_HANGING_SIGN = register(new Block("bamboo_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .booleanState(ATTACHED) .intState(ROTATION_16, 0, 15) .booleanState(WATERLOGGED))); - public static final Block OAK_WALL_HANGING_SIGN = register(new Block("oak_wall_hanging_sign", builder() + public static final Block OAK_WALL_HANGING_SIGN = register(new Block("oak_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block SPRUCE_WALL_HANGING_SIGN = register(new Block("spruce_wall_hanging_sign", builder() + public static final Block SPRUCE_WALL_HANGING_SIGN = register(new Block("spruce_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block BIRCH_WALL_HANGING_SIGN = register(new Block("birch_wall_hanging_sign", builder() + public static final Block BIRCH_WALL_HANGING_SIGN = register(new Block("birch_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block ACACIA_WALL_HANGING_SIGN = register(new Block("acacia_wall_hanging_sign", builder() + public static final Block ACACIA_WALL_HANGING_SIGN = register(new Block("acacia_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block CHERRY_WALL_HANGING_SIGN = register(new Block("cherry_wall_hanging_sign", builder() + public static final Block CHERRY_WALL_HANGING_SIGN = register(new Block("cherry_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block JUNGLE_WALL_HANGING_SIGN = register(new Block("jungle_wall_hanging_sign", builder() + public static final Block JUNGLE_WALL_HANGING_SIGN = register(new Block("jungle_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block DARK_OAK_WALL_HANGING_SIGN = register(new Block("dark_oak_wall_hanging_sign", builder() + public static final Block DARK_OAK_WALL_HANGING_SIGN = register(new Block("dark_oak_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block MANGROVE_WALL_HANGING_SIGN = register(new Block("mangrove_wall_hanging_sign", builder() + public static final Block MANGROVE_WALL_HANGING_SIGN = register(new Block("mangrove_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block CRIMSON_WALL_HANGING_SIGN = register(new Block("crimson_wall_hanging_sign", builder() + public static final Block CRIMSON_WALL_HANGING_SIGN = register(new Block("crimson_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block WARPED_WALL_HANGING_SIGN = register(new Block("warped_wall_hanging_sign", builder() + public static final Block WARPED_WALL_HANGING_SIGN = register(new Block("warped_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block BAMBOO_WALL_HANGING_SIGN = register(new Block("bamboo_wall_hanging_sign", builder() + public static final Block BAMBOO_WALL_HANGING_SIGN = register(new Block("bamboo_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block LEVER = register(new Block("lever", builder() + public static final Block LEVER = register(new Block("lever", builder().destroyTime(0.5f) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block STONE_PRESSURE_PLATE = register(new Block("stone_pressure_plate", builder() + public static final Block STONE_PRESSURE_PLATE = register(new Block("stone_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f) .booleanState(POWERED))); - public static final Block IRON_DOOR = register(new Block("iron_door", builder() + public static final Block IRON_DOOR = register(new Block("iron_door", builder().requiresCorrectToolForDrops().destroyTime(5.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block OAK_PRESSURE_PLATE = register(new Block("oak_pressure_plate", builder() + public static final Block OAK_PRESSURE_PLATE = register(new Block("oak_pressure_plate", builder().destroyTime(0.5f) .booleanState(POWERED))); - public static final Block SPRUCE_PRESSURE_PLATE = register(new Block("spruce_pressure_plate", builder() + public static final Block SPRUCE_PRESSURE_PLATE = register(new Block("spruce_pressure_plate", builder().destroyTime(0.5f) .booleanState(POWERED))); - public static final Block BIRCH_PRESSURE_PLATE = register(new Block("birch_pressure_plate", builder() + public static final Block BIRCH_PRESSURE_PLATE = register(new Block("birch_pressure_plate", builder().destroyTime(0.5f) .booleanState(POWERED))); - public static final Block JUNGLE_PRESSURE_PLATE = register(new Block("jungle_pressure_plate", builder() + public static final Block JUNGLE_PRESSURE_PLATE = register(new Block("jungle_pressure_plate", builder().destroyTime(0.5f) .booleanState(POWERED))); - public static final Block ACACIA_PRESSURE_PLATE = register(new Block("acacia_pressure_plate", builder() + public static final Block ACACIA_PRESSURE_PLATE = register(new Block("acacia_pressure_plate", builder().destroyTime(0.5f) .booleanState(POWERED))); - public static final Block CHERRY_PRESSURE_PLATE = register(new Block("cherry_pressure_plate", builder() + public static final Block CHERRY_PRESSURE_PLATE = register(new Block("cherry_pressure_plate", builder().destroyTime(0.5f) .booleanState(POWERED))); - public static final Block DARK_OAK_PRESSURE_PLATE = register(new Block("dark_oak_pressure_plate", builder() + public static final Block DARK_OAK_PRESSURE_PLATE = register(new Block("dark_oak_pressure_plate", builder().destroyTime(0.5f) .booleanState(POWERED))); - public static final Block MANGROVE_PRESSURE_PLATE = register(new Block("mangrove_pressure_plate", builder() + public static final Block MANGROVE_PRESSURE_PLATE = register(new Block("mangrove_pressure_plate", builder().destroyTime(0.5f) .booleanState(POWERED))); - public static final Block BAMBOO_PRESSURE_PLATE = register(new Block("bamboo_pressure_plate", builder() + public static final Block BAMBOO_PRESSURE_PLATE = register(new Block("bamboo_pressure_plate", builder().destroyTime(0.5f) .booleanState(POWERED))); - public static final Block REDSTONE_ORE = register(new Block("redstone_ore", builder() + public static final Block REDSTONE_ORE = register(new Block("redstone_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .booleanState(LIT))); - public static final Block DEEPSLATE_REDSTONE_ORE = register(new Block("deepslate_redstone_ore", builder() + public static final Block DEEPSLATE_REDSTONE_ORE = register(new Block("deepslate_redstone_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f) .booleanState(LIT))); public static final Block REDSTONE_TORCH = register(new Block("redstone_torch", builder() .booleanState(LIT))); public static final Block REDSTONE_WALL_TORCH = register(new Block("redstone_wall_torch", builder() .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(LIT))); - public static final Block STONE_BUTTON = register(new Block("stone_button", builder() + public static final Block STONE_BUTTON = register(new Block("stone_button", builder().destroyTime(0.5f) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block SNOW = register(new Block("snow", builder() + public static final Block SNOW = register(new Block("snow", builder().requiresCorrectToolForDrops().destroyTime(0.1f) .intState(LAYERS, 1, 8))); - public static final Block ICE = register(new Block("ice", builder())); - public static final Block SNOW_BLOCK = register(new Block("snow_block", builder())); - public static final Block CACTUS = register(new Block("cactus", builder() + public static final Block ICE = register(new Block("ice", builder().destroyTime(0.5f))); + public static final Block SNOW_BLOCK = register(new Block("snow_block", builder().requiresCorrectToolForDrops().destroyTime(0.2f))); + public static final Block CACTUS = register(new Block("cactus", builder().destroyTime(0.4f) .intState(AGE_15, 0, 15))); - public static final Block CLAY = register(new Block("clay", builder())); + public static final Block CLAY = register(new Block("clay", builder().destroyTime(0.6f))); public static final Block SUGAR_CANE = register(new Block("sugar_cane", builder() .intState(AGE_15, 0, 15))); - public static final Block JUKEBOX = register(new Block("jukebox", builder() + public static final Block JUKEBOX = register(new Block("jukebox", builder().setBlockEntity().destroyTime(2.0f) .booleanState(HAS_RECORD))); - public static final Block OAK_FENCE = register(new Block("oak_fence", builder() + public static final Block OAK_FENCE = register(new Block("oak_fence", builder().destroyTime(2.0f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block NETHERRACK = register(new Block("netherrack", builder())); - public static final Block SOUL_SAND = register(new Block("soul_sand", builder())); - public static final Block SOUL_SOIL = register(new Block("soul_soil", builder())); - public static final Block BASALT = register(new Block("basalt", builder() + public static final Block NETHERRACK = register(new Block("netherrack", builder().requiresCorrectToolForDrops().destroyTime(0.4f))); + public static final Block SOUL_SAND = register(new Block("soul_sand", builder().destroyTime(0.5f))); + public static final Block SOUL_SOIL = register(new Block("soul_soil", builder().destroyTime(0.5f))); + public static final Block BASALT = register(new Block("basalt", builder().requiresCorrectToolForDrops().destroyTime(1.25f) .enumState(AXIS, Axis.VALUES))); - public static final Block POLISHED_BASALT = register(new Block("polished_basalt", builder() + public static final Block POLISHED_BASALT = register(new Block("polished_basalt", builder().requiresCorrectToolForDrops().destroyTime(1.25f) .enumState(AXIS, Axis.VALUES))); public static final Block SOUL_TORCH = register(new Block("soul_torch", builder())); public static final Block SOUL_WALL_TORCH = register(new Block("soul_wall_torch", builder() .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block GLOWSTONE = register(new Block("glowstone", builder())); - public static final Block NETHER_PORTAL = register(new Block("nether_portal", builder() + public static final Block GLOWSTONE = register(new Block("glowstone", builder().destroyTime(0.3f))); + public static final Block NETHER_PORTAL = register(new Block("nether_portal", builder().destroyTime(-1.0f) .enumState(HORIZONTAL_AXIS, Axis.X, Axis.Z))); - public static final Block CARVED_PUMPKIN = register(new Block("carved_pumpkin", builder() + public static final Block CARVED_PUMPKIN = register(new Block("carved_pumpkin", builder().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block JACK_O_LANTERN = register(new Block("jack_o_lantern", builder() + public static final Block JACK_O_LANTERN = register(new Block("jack_o_lantern", builder().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block CAKE = register(new Block("cake", builder() + public static final Block CAKE = register(new Block("cake", builder().destroyTime(0.5f) .intState(BITES, 0, 6))); public static final Block REPEATER = register(new Block("repeater", builder() .intState(DELAY, 1, 4) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(LOCKED) .booleanState(POWERED))); - public static final Block WHITE_STAINED_GLASS = register(new Block("white_stained_glass", builder())); - public static final Block ORANGE_STAINED_GLASS = register(new Block("orange_stained_glass", builder())); - public static final Block MAGENTA_STAINED_GLASS = register(new Block("magenta_stained_glass", builder())); - public static final Block LIGHT_BLUE_STAINED_GLASS = register(new Block("light_blue_stained_glass", builder())); - public static final Block YELLOW_STAINED_GLASS = register(new Block("yellow_stained_glass", builder())); - public static final Block LIME_STAINED_GLASS = register(new Block("lime_stained_glass", builder())); - public static final Block PINK_STAINED_GLASS = register(new Block("pink_stained_glass", builder())); - public static final Block GRAY_STAINED_GLASS = register(new Block("gray_stained_glass", builder())); - public static final Block LIGHT_GRAY_STAINED_GLASS = register(new Block("light_gray_stained_glass", builder())); - public static final Block CYAN_STAINED_GLASS = register(new Block("cyan_stained_glass", builder())); - public static final Block PURPLE_STAINED_GLASS = register(new Block("purple_stained_glass", builder())); - public static final Block BLUE_STAINED_GLASS = register(new Block("blue_stained_glass", builder())); - public static final Block BROWN_STAINED_GLASS = register(new Block("brown_stained_glass", builder())); - public static final Block GREEN_STAINED_GLASS = register(new Block("green_stained_glass", builder())); - public static final Block RED_STAINED_GLASS = register(new Block("red_stained_glass", builder())); - public static final Block BLACK_STAINED_GLASS = register(new Block("black_stained_glass", builder())); - public static final Block OAK_TRAPDOOR = register(new Block("oak_trapdoor", builder() + public static final Block WHITE_STAINED_GLASS = register(new Block("white_stained_glass", builder().destroyTime(0.3f))); + public static final Block ORANGE_STAINED_GLASS = register(new Block("orange_stained_glass", builder().destroyTime(0.3f))); + public static final Block MAGENTA_STAINED_GLASS = register(new Block("magenta_stained_glass", builder().destroyTime(0.3f))); + public static final Block LIGHT_BLUE_STAINED_GLASS = register(new Block("light_blue_stained_glass", builder().destroyTime(0.3f))); + public static final Block YELLOW_STAINED_GLASS = register(new Block("yellow_stained_glass", builder().destroyTime(0.3f))); + public static final Block LIME_STAINED_GLASS = register(new Block("lime_stained_glass", builder().destroyTime(0.3f))); + public static final Block PINK_STAINED_GLASS = register(new Block("pink_stained_glass", builder().destroyTime(0.3f))); + public static final Block GRAY_STAINED_GLASS = register(new Block("gray_stained_glass", builder().destroyTime(0.3f))); + public static final Block LIGHT_GRAY_STAINED_GLASS = register(new Block("light_gray_stained_glass", builder().destroyTime(0.3f))); + public static final Block CYAN_STAINED_GLASS = register(new Block("cyan_stained_glass", builder().destroyTime(0.3f))); + public static final Block PURPLE_STAINED_GLASS = register(new Block("purple_stained_glass", builder().destroyTime(0.3f))); + public static final Block BLUE_STAINED_GLASS = register(new Block("blue_stained_glass", builder().destroyTime(0.3f))); + public static final Block BROWN_STAINED_GLASS = register(new Block("brown_stained_glass", builder().destroyTime(0.3f))); + public static final Block GREEN_STAINED_GLASS = register(new Block("green_stained_glass", builder().destroyTime(0.3f))); + public static final Block RED_STAINED_GLASS = register(new Block("red_stained_glass", builder().destroyTime(0.3f))); + public static final Block BLACK_STAINED_GLASS = register(new Block("black_stained_glass", builder().destroyTime(0.3f))); + public static final Block OAK_TRAPDOOR = register(new Block("oak_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block SPRUCE_TRAPDOOR = register(new Block("spruce_trapdoor", builder() + public static final Block SPRUCE_TRAPDOOR = register(new Block("spruce_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block BIRCH_TRAPDOOR = register(new Block("birch_trapdoor", builder() + public static final Block BIRCH_TRAPDOOR = register(new Block("birch_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block JUNGLE_TRAPDOOR = register(new Block("jungle_trapdoor", builder() + public static final Block JUNGLE_TRAPDOOR = register(new Block("jungle_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block ACACIA_TRAPDOOR = register(new Block("acacia_trapdoor", builder() + public static final Block ACACIA_TRAPDOOR = register(new Block("acacia_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block CHERRY_TRAPDOOR = register(new Block("cherry_trapdoor", builder() + public static final Block CHERRY_TRAPDOOR = register(new Block("cherry_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block DARK_OAK_TRAPDOOR = register(new Block("dark_oak_trapdoor", builder() + public static final Block DARK_OAK_TRAPDOOR = register(new Block("dark_oak_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block MANGROVE_TRAPDOOR = register(new Block("mangrove_trapdoor", builder() + public static final Block MANGROVE_TRAPDOOR = register(new Block("mangrove_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block BAMBOO_TRAPDOOR = register(new Block("bamboo_trapdoor", builder() + public static final Block BAMBOO_TRAPDOOR = register(new Block("bamboo_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block STONE_BRICKS = register(new Block("stone_bricks", builder())); - public static final Block MOSSY_STONE_BRICKS = register(new Block("mossy_stone_bricks", builder())); - public static final Block CRACKED_STONE_BRICKS = register(new Block("cracked_stone_bricks", builder())); - public static final Block CHISELED_STONE_BRICKS = register(new Block("chiseled_stone_bricks", builder())); - public static final Block PACKED_MUD = register(new Block("packed_mud", builder())); - public static final Block MUD_BRICKS = register(new Block("mud_bricks", builder())); - public static final Block INFESTED_STONE = register(new Block("infested_stone", builder())); - public static final Block INFESTED_COBBLESTONE = register(new Block("infested_cobblestone", builder())); - public static final Block INFESTED_STONE_BRICKS = register(new Block("infested_stone_bricks", builder())); - public static final Block INFESTED_MOSSY_STONE_BRICKS = register(new Block("infested_mossy_stone_bricks", builder())); - public static final Block INFESTED_CRACKED_STONE_BRICKS = register(new Block("infested_cracked_stone_bricks", builder())); - public static final Block INFESTED_CHISELED_STONE_BRICKS = register(new Block("infested_chiseled_stone_bricks", builder())); - public static final Block BROWN_MUSHROOM_BLOCK = register(new Block("brown_mushroom_block", builder() + public static final Block STONE_BRICKS = register(new Block("stone_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block MOSSY_STONE_BRICKS = register(new Block("mossy_stone_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block CRACKED_STONE_BRICKS = register(new Block("cracked_stone_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block CHISELED_STONE_BRICKS = register(new Block("chiseled_stone_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block PACKED_MUD = register(new Block("packed_mud", builder().destroyTime(1.0f))); + public static final Block MUD_BRICKS = register(new Block("mud_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block INFESTED_STONE = register(new Block("infested_stone", builder().destroyTime(0.75f))); + public static final Block INFESTED_COBBLESTONE = register(new Block("infested_cobblestone", builder().destroyTime(1.0f))); + public static final Block INFESTED_STONE_BRICKS = register(new Block("infested_stone_bricks", builder().destroyTime(0.75f))); + public static final Block INFESTED_MOSSY_STONE_BRICKS = register(new Block("infested_mossy_stone_bricks", builder().destroyTime(0.75f))); + public static final Block INFESTED_CRACKED_STONE_BRICKS = register(new Block("infested_cracked_stone_bricks", builder().destroyTime(0.75f))); + public static final Block INFESTED_CHISELED_STONE_BRICKS = register(new Block("infested_chiseled_stone_bricks", builder().destroyTime(0.75f))); + public static final Block BROWN_MUSHROOM_BLOCK = register(new Block("brown_mushroom_block", builder().destroyTime(0.2f) .booleanState(DOWN) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(UP) .booleanState(WEST))); - public static final Block RED_MUSHROOM_BLOCK = register(new Block("red_mushroom_block", builder() + public static final Block RED_MUSHROOM_BLOCK = register(new Block("red_mushroom_block", builder().destroyTime(0.2f) .booleanState(DOWN) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(UP) .booleanState(WEST))); - public static final Block MUSHROOM_STEM = register(new Block("mushroom_stem", builder() + public static final Block MUSHROOM_STEM = register(new Block("mushroom_stem", builder().destroyTime(0.2f) .booleanState(DOWN) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(UP) .booleanState(WEST))); - public static final Block IRON_BARS = register(new Block("iron_bars", builder() + public static final Block IRON_BARS = register(new Block("iron_bars", builder().requiresCorrectToolForDrops().destroyTime(5.0f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block CHAIN = register(new Block("chain", builder() + public static final Block CHAIN = register(new Block("chain", builder().requiresCorrectToolForDrops().destroyTime(5.0f) .enumState(AXIS, Axis.VALUES) .booleanState(WATERLOGGED))); - public static final Block GLASS_PANE = register(new Block("glass_pane", builder() + public static final Block GLASS_PANE = register(new Block("glass_pane", builder().destroyTime(0.3f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block PUMPKIN = register(new Block("pumpkin", builder())); - public static final Block MELON = register(new Block("melon", builder())); + public static final Block PUMPKIN = register(new Block("pumpkin", builder().destroyTime(1.0f))); + public static final Block MELON = register(new Block("melon", builder().destroyTime(1.0f))); public static final Block ATTACHED_PUMPKIN_STEM = register(new Block("attached_pumpkin_stem", builder() .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); public static final Block ATTACHED_MELON_STEM = register(new Block("attached_melon_stem", builder() @@ -766,13 +766,13 @@ public final class Blocks { .intState(AGE_7, 0, 7))); public static final Block MELON_STEM = register(new Block("melon_stem", builder() .intState(AGE_7, 0, 7))); - public static final Block VINE = register(new Block("vine", builder() + public static final Block VINE = register(new Block("vine", builder().destroyTime(0.2f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(UP) .booleanState(WEST))); - public static final Block GLOW_LICHEN = register(new Block("glow_lichen", builder() + public static final Block GLOW_LICHEN = register(new Block("glow_lichen", builder().destroyTime(0.2f) .booleanState(DOWN) .booleanState(EAST) .booleanState(NORTH) @@ -780,73 +780,73 @@ public final class Blocks { .booleanState(UP) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block OAK_FENCE_GATE = register(new Block("oak_fence_gate", builder() + public static final Block OAK_FENCE_GATE = register(new Block("oak_fence_gate", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(IN_WALL) .booleanState(OPEN) .booleanState(POWERED))); - public static final Block BRICK_STAIRS = register(new Block("brick_stairs", builder() + public static final Block BRICK_STAIRS = register(new Block("brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block STONE_BRICK_STAIRS = register(new Block("stone_brick_stairs", builder() + public static final Block STONE_BRICK_STAIRS = register(new Block("stone_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block MUD_BRICK_STAIRS = register(new Block("mud_brick_stairs", builder() + public static final Block MUD_BRICK_STAIRS = register(new Block("mud_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block MYCELIUM = register(new Block("mycelium", builder() + public static final Block MYCELIUM = register(new Block("mycelium", builder().destroyTime(0.6f) .booleanState(SNOWY))); public static final Block LILY_PAD = register(new Block("lily_pad", builder())); - public static final Block NETHER_BRICKS = register(new Block("nether_bricks", builder())); - public static final Block NETHER_BRICK_FENCE = register(new Block("nether_brick_fence", builder() + public static final Block NETHER_BRICKS = register(new Block("nether_bricks", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); + public static final Block NETHER_BRICK_FENCE = register(new Block("nether_brick_fence", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block NETHER_BRICK_STAIRS = register(new Block("nether_brick_stairs", builder() + public static final Block NETHER_BRICK_STAIRS = register(new Block("nether_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); public static final Block NETHER_WART = register(new Block("nether_wart", builder() .intState(AGE_3, 0, 3))); - public static final Block ENCHANTING_TABLE = register(new Block("enchanting_table", builder())); - public static final Block BREWING_STAND = register(new Block("brewing_stand", builder() + public static final Block ENCHANTING_TABLE = register(new Block("enchanting_table", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(5.0f))); + public static final Block BREWING_STAND = register(new Block("brewing_stand", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(0.5f) .booleanState(HAS_BOTTLE_0) .booleanState(HAS_BOTTLE_1) .booleanState(HAS_BOTTLE_2))); - public static final Block CAULDRON = register(new Block("cauldron", builder())); - public static final Block WATER_CAULDRON = register(new Block("water_cauldron", builder() + public static final Block CAULDRON = register(new Block("cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); + public static final Block WATER_CAULDRON = register(new Block("water_cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .intState(LEVEL_CAULDRON, 1, 3))); - public static final Block LAVA_CAULDRON = register(new Block("lava_cauldron", builder())); - public static final Block POWDER_SNOW_CAULDRON = register(new Block("powder_snow_cauldron", builder() + public static final Block LAVA_CAULDRON = register(new Block("lava_cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); + public static final Block POWDER_SNOW_CAULDRON = register(new Block("powder_snow_cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .intState(LEVEL_CAULDRON, 1, 3))); - public static final Block END_PORTAL = register(new Block("end_portal", builder())); - public static final Block END_PORTAL_FRAME = register(new Block("end_portal_frame", builder() + public static final Block END_PORTAL = register(new Block("end_portal", builder().setBlockEntity().destroyTime(-1.0f))); + public static final Block END_PORTAL_FRAME = register(new Block("end_portal_frame", builder().destroyTime(-1.0f) .booleanState(EYE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block END_STONE = register(new Block("end_stone", builder())); - public static final Block DRAGON_EGG = register(new Block("dragon_egg", builder())); - public static final Block REDSTONE_LAMP = register(new Block("redstone_lamp", builder() + public static final Block END_STONE = register(new Block("end_stone", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block DRAGON_EGG = register(new Block("dragon_egg", builder().destroyTime(3.0f))); + public static final Block REDSTONE_LAMP = register(new Block("redstone_lamp", builder().destroyTime(0.3f) .booleanState(LIT))); - public static final Block COCOA = register(new Block("cocoa", builder() + public static final Block COCOA = register(new Block("cocoa", builder().destroyTime(0.2f) .intState(AGE_2, 0, 2) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block SANDSTONE_STAIRS = register(new Block("sandstone_stairs", builder() + public static final Block SANDSTONE_STAIRS = register(new Block("sandstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(0.8f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block EMERALD_ORE = register(new Block("emerald_ore", builder())); - public static final Block DEEPSLATE_EMERALD_ORE = register(new Block("deepslate_emerald_ore", builder())); - public static final Block ENDER_CHEST = register(new Block("ender_chest", builder() + public static final Block EMERALD_ORE = register(new Block("emerald_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block DEEPSLATE_EMERALD_ORE = register(new Block("deepslate_emerald_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f))); + public static final Block ENDER_CHEST = register(new Block("ender_chest", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(22.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); public static final Block TRIPWIRE_HOOK = register(new Block("tripwire_hook", builder() @@ -861,34 +861,34 @@ public final class Blocks { .booleanState(POWERED) .booleanState(SOUTH) .booleanState(WEST))); - public static final Block EMERALD_BLOCK = register(new Block("emerald_block", builder())); - public static final Block SPRUCE_STAIRS = register(new Block("spruce_stairs", builder() + public static final Block EMERALD_BLOCK = register(new Block("emerald_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f))); + public static final Block SPRUCE_STAIRS = register(new Block("spruce_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block BIRCH_STAIRS = register(new Block("birch_stairs", builder() + public static final Block BIRCH_STAIRS = register(new Block("birch_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block JUNGLE_STAIRS = register(new Block("jungle_stairs", builder() + public static final Block JUNGLE_STAIRS = register(new Block("jungle_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block COMMAND_BLOCK = register(new Block("command_block", builder() + public static final Block COMMAND_BLOCK = register(new Block("command_block", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(-1.0f) .booleanState(CONDITIONAL) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block BEACON = register(new Block("beacon", builder())); - public static final Block COBBLESTONE_WALL = register(new Block("cobblestone_wall", builder() + public static final Block BEACON = register(new Block("beacon", builder().setBlockEntity().destroyTime(3.0f))); + public static final Block COBBLESTONE_WALL = register(new Block("cobblestone_wall", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(EAST_WALL, "none", "low", "tall") .enumState(NORTH_WALL, "none", "low", "tall") .enumState(SOUTH_WALL, "none", "low", "tall") .booleanState(UP) .booleanState(WATERLOGGED) .enumState(WEST_WALL, "none", "low", "tall"))); - public static final Block MOSSY_COBBLESTONE_WALL = register(new Block("mossy_cobblestone_wall", builder() + public static final Block MOSSY_COBBLESTONE_WALL = register(new Block("mossy_cobblestone_wall", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(EAST_WALL, "none", "low", "tall") .enumState(NORTH_WALL, "none", "low", "tall") .enumState(SOUTH_WALL, "none", "low", "tall") @@ -927,329 +927,329 @@ public final class Blocks { .intState(AGE_7, 0, 7))); public static final Block POTATOES = register(new Block("potatoes", builder() .intState(AGE_7, 0, 7))); - public static final Block OAK_BUTTON = register(new Block("oak_button", builder() + public static final Block OAK_BUTTON = register(new Block("oak_button", builder().destroyTime(0.5f) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block SPRUCE_BUTTON = register(new Block("spruce_button", builder() + public static final Block SPRUCE_BUTTON = register(new Block("spruce_button", builder().destroyTime(0.5f) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block BIRCH_BUTTON = register(new Block("birch_button", builder() + public static final Block BIRCH_BUTTON = register(new Block("birch_button", builder().destroyTime(0.5f) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block JUNGLE_BUTTON = register(new Block("jungle_button", builder() + public static final Block JUNGLE_BUTTON = register(new Block("jungle_button", builder().destroyTime(0.5f) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block ACACIA_BUTTON = register(new Block("acacia_button", builder() + public static final Block ACACIA_BUTTON = register(new Block("acacia_button", builder().destroyTime(0.5f) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block CHERRY_BUTTON = register(new Block("cherry_button", builder() + public static final Block CHERRY_BUTTON = register(new Block("cherry_button", builder().destroyTime(0.5f) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block DARK_OAK_BUTTON = register(new Block("dark_oak_button", builder() + public static final Block DARK_OAK_BUTTON = register(new Block("dark_oak_button", builder().destroyTime(0.5f) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block MANGROVE_BUTTON = register(new Block("mangrove_button", builder() + public static final Block MANGROVE_BUTTON = register(new Block("mangrove_button", builder().destroyTime(0.5f) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block BAMBOO_BUTTON = register(new Block("bamboo_button", builder() + public static final Block BAMBOO_BUTTON = register(new Block("bamboo_button", builder().destroyTime(0.5f) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block SKELETON_SKULL = register(new Block("skeleton_skull", builder() + public static final Block SKELETON_SKULL = register(new Block("skeleton_skull", builder().setBlockEntity().destroyTime(1.0f) .booleanState(POWERED) .intState(ROTATION_16, 0, 15))); - public static final Block SKELETON_WALL_SKULL = register(new Block("skeleton_wall_skull", builder() + public static final Block SKELETON_WALL_SKULL = register(new Block("skeleton_wall_skull", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block WITHER_SKELETON_SKULL = register(new Block("wither_skeleton_skull", builder() + public static final Block WITHER_SKELETON_SKULL = register(new Block("wither_skeleton_skull", builder().setBlockEntity().destroyTime(1.0f) .booleanState(POWERED) .intState(ROTATION_16, 0, 15))); - public static final Block WITHER_SKELETON_WALL_SKULL = register(new Block("wither_skeleton_wall_skull", builder() + public static final Block WITHER_SKELETON_WALL_SKULL = register(new Block("wither_skeleton_wall_skull", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block ZOMBIE_HEAD = register(new Block("zombie_head", builder() + public static final Block ZOMBIE_HEAD = register(new Block("zombie_head", builder().setBlockEntity().destroyTime(1.0f) .booleanState(POWERED) .intState(ROTATION_16, 0, 15))); - public static final Block ZOMBIE_WALL_HEAD = register(new Block("zombie_wall_head", builder() + public static final Block ZOMBIE_WALL_HEAD = register(new Block("zombie_wall_head", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block PLAYER_HEAD = register(new Block("player_head", builder() + public static final Block PLAYER_HEAD = register(new Block("player_head", builder().setBlockEntity().destroyTime(1.0f) .booleanState(POWERED) .intState(ROTATION_16, 0, 15))); - public static final Block PLAYER_WALL_HEAD = register(new Block("player_wall_head", builder() + public static final Block PLAYER_WALL_HEAD = register(new Block("player_wall_head", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block CREEPER_HEAD = register(new Block("creeper_head", builder() + public static final Block CREEPER_HEAD = register(new Block("creeper_head", builder().setBlockEntity().destroyTime(1.0f) .booleanState(POWERED) .intState(ROTATION_16, 0, 15))); - public static final Block CREEPER_WALL_HEAD = register(new Block("creeper_wall_head", builder() + public static final Block CREEPER_WALL_HEAD = register(new Block("creeper_wall_head", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block DRAGON_HEAD = register(new Block("dragon_head", builder() + public static final Block DRAGON_HEAD = register(new Block("dragon_head", builder().setBlockEntity().destroyTime(1.0f) .booleanState(POWERED) .intState(ROTATION_16, 0, 15))); - public static final Block DRAGON_WALL_HEAD = register(new Block("dragon_wall_head", builder() + public static final Block DRAGON_WALL_HEAD = register(new Block("dragon_wall_head", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block PIGLIN_HEAD = register(new Block("piglin_head", builder() + public static final Block PIGLIN_HEAD = register(new Block("piglin_head", builder().setBlockEntity().destroyTime(1.0f) .booleanState(POWERED) .intState(ROTATION_16, 0, 15))); - public static final Block PIGLIN_WALL_HEAD = register(new Block("piglin_wall_head", builder() + public static final Block PIGLIN_WALL_HEAD = register(new Block("piglin_wall_head", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block ANVIL = register(new Block("anvil", builder() + public static final Block ANVIL = register(new Block("anvil", builder().requiresCorrectToolForDrops().destroyTime(5.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block CHIPPED_ANVIL = register(new Block("chipped_anvil", builder() + public static final Block CHIPPED_ANVIL = register(new Block("chipped_anvil", builder().requiresCorrectToolForDrops().destroyTime(5.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block DAMAGED_ANVIL = register(new Block("damaged_anvil", builder() + public static final Block DAMAGED_ANVIL = register(new Block("damaged_anvil", builder().requiresCorrectToolForDrops().destroyTime(5.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block TRAPPED_CHEST = register(new Block("trapped_chest", builder() + public static final Block TRAPPED_CHEST = register(new Block("trapped_chest", builder().setBlockEntity().destroyTime(2.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(CHEST_TYPE, "single", "left", "right") .booleanState(WATERLOGGED))); - public static final Block LIGHT_WEIGHTED_PRESSURE_PLATE = register(new Block("light_weighted_pressure_plate", builder() + public static final Block LIGHT_WEIGHTED_PRESSURE_PLATE = register(new Block("light_weighted_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f) .intState(POWER, 0, 15))); - public static final Block HEAVY_WEIGHTED_PRESSURE_PLATE = register(new Block("heavy_weighted_pressure_plate", builder() + public static final Block HEAVY_WEIGHTED_PRESSURE_PLATE = register(new Block("heavy_weighted_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f) .intState(POWER, 0, 15))); - public static final Block COMPARATOR = register(new Block("comparator", builder() + public static final Block COMPARATOR = register(new Block("comparator", builder().setBlockEntity() .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(MODE_COMPARATOR, "compare", "subtract") .booleanState(POWERED))); - public static final Block DAYLIGHT_DETECTOR = register(new Block("daylight_detector", builder() + public static final Block DAYLIGHT_DETECTOR = register(new Block("daylight_detector", builder().setBlockEntity().destroyTime(0.2f) .booleanState(INVERTED) .intState(POWER, 0, 15))); - public static final Block REDSTONE_BLOCK = register(new Block("redstone_block", builder())); - public static final Block NETHER_QUARTZ_ORE = register(new Block("nether_quartz_ore", builder())); - public static final Block HOPPER = register(new Block("hopper", builder() + public static final Block REDSTONE_BLOCK = register(new Block("redstone_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f))); + public static final Block NETHER_QUARTZ_ORE = register(new Block("nether_quartz_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block HOPPER = register(new Block("hopper", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(3.0f) .booleanState(ENABLED) .enumState(FACING_HOPPER, Direction.DOWN, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block QUARTZ_BLOCK = register(new Block("quartz_block", builder())); - public static final Block CHISELED_QUARTZ_BLOCK = register(new Block("chiseled_quartz_block", builder())); - public static final Block QUARTZ_PILLAR = register(new Block("quartz_pillar", builder() + public static final Block QUARTZ_BLOCK = register(new Block("quartz_block", builder().requiresCorrectToolForDrops().destroyTime(0.8f))); + public static final Block CHISELED_QUARTZ_BLOCK = register(new Block("chiseled_quartz_block", builder().requiresCorrectToolForDrops().destroyTime(0.8f))); + public static final Block QUARTZ_PILLAR = register(new Block("quartz_pillar", builder().requiresCorrectToolForDrops().destroyTime(0.8f) .enumState(AXIS, Axis.VALUES))); - public static final Block QUARTZ_STAIRS = register(new Block("quartz_stairs", builder() + public static final Block QUARTZ_STAIRS = register(new Block("quartz_stairs", builder().requiresCorrectToolForDrops().destroyTime(0.8f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block ACTIVATOR_RAIL = register(new Block("activator_rail", builder() + public static final Block ACTIVATOR_RAIL = register(new Block("activator_rail", builder().destroyTime(0.7f) .booleanState(POWERED) .enumState(RAIL_SHAPE_STRAIGHT, "north_south", "east_west", "ascending_east", "ascending_west", "ascending_north", "ascending_south") .booleanState(WATERLOGGED))); - public static final Block DROPPER = register(new Block("dropper", builder() + public static final Block DROPPER = register(new Block("dropper", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .booleanState(TRIGGERED))); - public static final Block WHITE_TERRACOTTA = register(new Block("white_terracotta", builder())); - public static final Block ORANGE_TERRACOTTA = register(new Block("orange_terracotta", builder())); - public static final Block MAGENTA_TERRACOTTA = register(new Block("magenta_terracotta", builder())); - public static final Block LIGHT_BLUE_TERRACOTTA = register(new Block("light_blue_terracotta", builder())); - public static final Block YELLOW_TERRACOTTA = register(new Block("yellow_terracotta", builder())); - public static final Block LIME_TERRACOTTA = register(new Block("lime_terracotta", builder())); - public static final Block PINK_TERRACOTTA = register(new Block("pink_terracotta", builder())); - public static final Block GRAY_TERRACOTTA = register(new Block("gray_terracotta", builder())); - public static final Block LIGHT_GRAY_TERRACOTTA = register(new Block("light_gray_terracotta", builder())); - public static final Block CYAN_TERRACOTTA = register(new Block("cyan_terracotta", builder())); - public static final Block PURPLE_TERRACOTTA = register(new Block("purple_terracotta", builder())); - public static final Block BLUE_TERRACOTTA = register(new Block("blue_terracotta", builder())); - public static final Block BROWN_TERRACOTTA = register(new Block("brown_terracotta", builder())); - public static final Block GREEN_TERRACOTTA = register(new Block("green_terracotta", builder())); - public static final Block RED_TERRACOTTA = register(new Block("red_terracotta", builder())); - public static final Block BLACK_TERRACOTTA = register(new Block("black_terracotta", builder())); - public static final Block WHITE_STAINED_GLASS_PANE = register(new Block("white_stained_glass_pane", builder() + public static final Block WHITE_TERRACOTTA = register(new Block("white_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f))); + public static final Block ORANGE_TERRACOTTA = register(new Block("orange_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f))); + public static final Block MAGENTA_TERRACOTTA = register(new Block("magenta_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f))); + public static final Block LIGHT_BLUE_TERRACOTTA = register(new Block("light_blue_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f))); + public static final Block YELLOW_TERRACOTTA = register(new Block("yellow_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f))); + public static final Block LIME_TERRACOTTA = register(new Block("lime_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f))); + public static final Block PINK_TERRACOTTA = register(new Block("pink_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f))); + public static final Block GRAY_TERRACOTTA = register(new Block("gray_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f))); + public static final Block LIGHT_GRAY_TERRACOTTA = register(new Block("light_gray_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f))); + public static final Block CYAN_TERRACOTTA = register(new Block("cyan_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f))); + public static final Block PURPLE_TERRACOTTA = register(new Block("purple_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f))); + public static final Block BLUE_TERRACOTTA = register(new Block("blue_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f))); + public static final Block BROWN_TERRACOTTA = register(new Block("brown_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f))); + public static final Block GREEN_TERRACOTTA = register(new Block("green_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f))); + public static final Block RED_TERRACOTTA = register(new Block("red_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f))); + public static final Block BLACK_TERRACOTTA = register(new Block("black_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f))); + public static final Block WHITE_STAINED_GLASS_PANE = register(new Block("white_stained_glass_pane", builder().destroyTime(0.3f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block ORANGE_STAINED_GLASS_PANE = register(new Block("orange_stained_glass_pane", builder() + public static final Block ORANGE_STAINED_GLASS_PANE = register(new Block("orange_stained_glass_pane", builder().destroyTime(0.3f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block MAGENTA_STAINED_GLASS_PANE = register(new Block("magenta_stained_glass_pane", builder() + public static final Block MAGENTA_STAINED_GLASS_PANE = register(new Block("magenta_stained_glass_pane", builder().destroyTime(0.3f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block LIGHT_BLUE_STAINED_GLASS_PANE = register(new Block("light_blue_stained_glass_pane", builder() + public static final Block LIGHT_BLUE_STAINED_GLASS_PANE = register(new Block("light_blue_stained_glass_pane", builder().destroyTime(0.3f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block YELLOW_STAINED_GLASS_PANE = register(new Block("yellow_stained_glass_pane", builder() + public static final Block YELLOW_STAINED_GLASS_PANE = register(new Block("yellow_stained_glass_pane", builder().destroyTime(0.3f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block LIME_STAINED_GLASS_PANE = register(new Block("lime_stained_glass_pane", builder() + public static final Block LIME_STAINED_GLASS_PANE = register(new Block("lime_stained_glass_pane", builder().destroyTime(0.3f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block PINK_STAINED_GLASS_PANE = register(new Block("pink_stained_glass_pane", builder() + public static final Block PINK_STAINED_GLASS_PANE = register(new Block("pink_stained_glass_pane", builder().destroyTime(0.3f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block GRAY_STAINED_GLASS_PANE = register(new Block("gray_stained_glass_pane", builder() + public static final Block GRAY_STAINED_GLASS_PANE = register(new Block("gray_stained_glass_pane", builder().destroyTime(0.3f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block LIGHT_GRAY_STAINED_GLASS_PANE = register(new Block("light_gray_stained_glass_pane", builder() + public static final Block LIGHT_GRAY_STAINED_GLASS_PANE = register(new Block("light_gray_stained_glass_pane", builder().destroyTime(0.3f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block CYAN_STAINED_GLASS_PANE = register(new Block("cyan_stained_glass_pane", builder() + public static final Block CYAN_STAINED_GLASS_PANE = register(new Block("cyan_stained_glass_pane", builder().destroyTime(0.3f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block PURPLE_STAINED_GLASS_PANE = register(new Block("purple_stained_glass_pane", builder() + public static final Block PURPLE_STAINED_GLASS_PANE = register(new Block("purple_stained_glass_pane", builder().destroyTime(0.3f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block BLUE_STAINED_GLASS_PANE = register(new Block("blue_stained_glass_pane", builder() + public static final Block BLUE_STAINED_GLASS_PANE = register(new Block("blue_stained_glass_pane", builder().destroyTime(0.3f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block BROWN_STAINED_GLASS_PANE = register(new Block("brown_stained_glass_pane", builder() + public static final Block BROWN_STAINED_GLASS_PANE = register(new Block("brown_stained_glass_pane", builder().destroyTime(0.3f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block GREEN_STAINED_GLASS_PANE = register(new Block("green_stained_glass_pane", builder() + public static final Block GREEN_STAINED_GLASS_PANE = register(new Block("green_stained_glass_pane", builder().destroyTime(0.3f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block RED_STAINED_GLASS_PANE = register(new Block("red_stained_glass_pane", builder() + public static final Block RED_STAINED_GLASS_PANE = register(new Block("red_stained_glass_pane", builder().destroyTime(0.3f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block BLACK_STAINED_GLASS_PANE = register(new Block("black_stained_glass_pane", builder() + public static final Block BLACK_STAINED_GLASS_PANE = register(new Block("black_stained_glass_pane", builder().destroyTime(0.3f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block ACACIA_STAIRS = register(new Block("acacia_stairs", builder() + public static final Block ACACIA_STAIRS = register(new Block("acacia_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block CHERRY_STAIRS = register(new Block("cherry_stairs", builder() + public static final Block CHERRY_STAIRS = register(new Block("cherry_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block DARK_OAK_STAIRS = register(new Block("dark_oak_stairs", builder() + public static final Block DARK_OAK_STAIRS = register(new Block("dark_oak_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block MANGROVE_STAIRS = register(new Block("mangrove_stairs", builder() + public static final Block MANGROVE_STAIRS = register(new Block("mangrove_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block BAMBOO_STAIRS = register(new Block("bamboo_stairs", builder() + public static final Block BAMBOO_STAIRS = register(new Block("bamboo_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block BAMBOO_MOSAIC_STAIRS = register(new Block("bamboo_mosaic_stairs", builder() + public static final Block BAMBOO_MOSAIC_STAIRS = register(new Block("bamboo_mosaic_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); public static final Block SLIME_BLOCK = register(new Block("slime_block", builder())); - public static final Block BARRIER = register(new Block("barrier", builder() + public static final Block BARRIER = register(new Block("barrier", builder().destroyTime(-1.0f) .booleanState(WATERLOGGED))); - public static final Block LIGHT = register(new Block("light", builder() + public static final Block LIGHT = register(new Block("light", builder().destroyTime(-1.0f) .intState(LEVEL, 0, 15) .booleanState(WATERLOGGED))); - public static final Block IRON_TRAPDOOR = register(new Block("iron_trapdoor", builder() + public static final Block IRON_TRAPDOOR = register(new Block("iron_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(5.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block PRISMARINE = register(new Block("prismarine", builder())); - public static final Block PRISMARINE_BRICKS = register(new Block("prismarine_bricks", builder())); - public static final Block DARK_PRISMARINE = register(new Block("dark_prismarine", builder())); - public static final Block PRISMARINE_STAIRS = register(new Block("prismarine_stairs", builder() + public static final Block PRISMARINE = register(new Block("prismarine", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block PRISMARINE_BRICKS = register(new Block("prismarine_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block DARK_PRISMARINE = register(new Block("dark_prismarine", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block PRISMARINE_STAIRS = register(new Block("prismarine_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block PRISMARINE_BRICK_STAIRS = register(new Block("prismarine_brick_stairs", builder() + public static final Block PRISMARINE_BRICK_STAIRS = register(new Block("prismarine_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block DARK_PRISMARINE_STAIRS = register(new Block("dark_prismarine_stairs", builder() + public static final Block DARK_PRISMARINE_STAIRS = register(new Block("dark_prismarine_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block PRISMARINE_SLAB = register(new Block("prismarine_slab", builder() + public static final Block PRISMARINE_SLAB = register(new Block("prismarine_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block PRISMARINE_BRICK_SLAB = register(new Block("prismarine_brick_slab", builder() + public static final Block PRISMARINE_BRICK_SLAB = register(new Block("prismarine_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block DARK_PRISMARINE_SLAB = register(new Block("dark_prismarine_slab", builder() + public static final Block DARK_PRISMARINE_SLAB = register(new Block("dark_prismarine_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block SEA_LANTERN = register(new Block("sea_lantern", builder())); - public static final Block HAY_BLOCK = register(new Block("hay_block", builder() + public static final Block SEA_LANTERN = register(new Block("sea_lantern", builder().destroyTime(0.3f))); + public static final Block HAY_BLOCK = register(new Block("hay_block", builder().destroyTime(0.5f) .enumState(AXIS, Axis.VALUES))); - public static final Block WHITE_CARPET = register(new Block("white_carpet", builder())); - public static final Block ORANGE_CARPET = register(new Block("orange_carpet", builder())); - public static final Block MAGENTA_CARPET = register(new Block("magenta_carpet", builder())); - public static final Block LIGHT_BLUE_CARPET = register(new Block("light_blue_carpet", builder())); - public static final Block YELLOW_CARPET = register(new Block("yellow_carpet", builder())); - public static final Block LIME_CARPET = register(new Block("lime_carpet", builder())); - public static final Block PINK_CARPET = register(new Block("pink_carpet", builder())); - public static final Block GRAY_CARPET = register(new Block("gray_carpet", builder())); - public static final Block LIGHT_GRAY_CARPET = register(new Block("light_gray_carpet", builder())); - public static final Block CYAN_CARPET = register(new Block("cyan_carpet", builder())); - public static final Block PURPLE_CARPET = register(new Block("purple_carpet", builder())); - public static final Block BLUE_CARPET = register(new Block("blue_carpet", builder())); - public static final Block BROWN_CARPET = register(new Block("brown_carpet", builder())); - public static final Block GREEN_CARPET = register(new Block("green_carpet", builder())); - public static final Block RED_CARPET = register(new Block("red_carpet", builder())); - public static final Block BLACK_CARPET = register(new Block("black_carpet", builder())); - public static final Block TERRACOTTA = register(new Block("terracotta", builder())); - public static final Block COAL_BLOCK = register(new Block("coal_block", builder())); - public static final Block PACKED_ICE = register(new Block("packed_ice", builder())); + public static final Block WHITE_CARPET = register(new Block("white_carpet", builder().destroyTime(0.1f))); + public static final Block ORANGE_CARPET = register(new Block("orange_carpet", builder().destroyTime(0.1f))); + public static final Block MAGENTA_CARPET = register(new Block("magenta_carpet", builder().destroyTime(0.1f))); + public static final Block LIGHT_BLUE_CARPET = register(new Block("light_blue_carpet", builder().destroyTime(0.1f))); + public static final Block YELLOW_CARPET = register(new Block("yellow_carpet", builder().destroyTime(0.1f))); + public static final Block LIME_CARPET = register(new Block("lime_carpet", builder().destroyTime(0.1f))); + public static final Block PINK_CARPET = register(new Block("pink_carpet", builder().destroyTime(0.1f))); + public static final Block GRAY_CARPET = register(new Block("gray_carpet", builder().destroyTime(0.1f))); + public static final Block LIGHT_GRAY_CARPET = register(new Block("light_gray_carpet", builder().destroyTime(0.1f))); + public static final Block CYAN_CARPET = register(new Block("cyan_carpet", builder().destroyTime(0.1f))); + public static final Block PURPLE_CARPET = register(new Block("purple_carpet", builder().destroyTime(0.1f))); + public static final Block BLUE_CARPET = register(new Block("blue_carpet", builder().destroyTime(0.1f))); + public static final Block BROWN_CARPET = register(new Block("brown_carpet", builder().destroyTime(0.1f))); + public static final Block GREEN_CARPET = register(new Block("green_carpet", builder().destroyTime(0.1f))); + public static final Block RED_CARPET = register(new Block("red_carpet", builder().destroyTime(0.1f))); + public static final Block BLACK_CARPET = register(new Block("black_carpet", builder().destroyTime(0.1f))); + public static final Block TERRACOTTA = register(new Block("terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f))); + public static final Block COAL_BLOCK = register(new Block("coal_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f))); + public static final Block PACKED_ICE = register(new Block("packed_ice", builder().destroyTime(0.5f))); public static final Block SUNFLOWER = register(new Block("sunflower", builder() .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); public static final Block LILAC = register(new Block("lilac", builder() @@ -1262,285 +1262,285 @@ public final class Blocks { .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); public static final Block LARGE_FERN = register(new Block("large_fern", builder() .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); - public static final Block WHITE_BANNER = register(new BannerBlock("white_banner", 0, builder() + public static final Block WHITE_BANNER = register(new BannerBlock("white_banner", 0, builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15))); - public static final Block ORANGE_BANNER = register(new BannerBlock("orange_banner", 1, builder() + public static final Block ORANGE_BANNER = register(new BannerBlock("orange_banner", 1, builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15))); - public static final Block MAGENTA_BANNER = register(new BannerBlock("magenta_banner", 2, builder() + public static final Block MAGENTA_BANNER = register(new BannerBlock("magenta_banner", 2, builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15))); - public static final Block LIGHT_BLUE_BANNER = register(new BannerBlock("light_blue_banner", 3, builder() + public static final Block LIGHT_BLUE_BANNER = register(new BannerBlock("light_blue_banner", 3, builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15))); - public static final Block YELLOW_BANNER = register(new BannerBlock("yellow_banner", 4, builder() + public static final Block YELLOW_BANNER = register(new BannerBlock("yellow_banner", 4, builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15))); - public static final Block LIME_BANNER = register(new BannerBlock("lime_banner", 5, builder() + public static final Block LIME_BANNER = register(new BannerBlock("lime_banner", 5, builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15))); - public static final Block PINK_BANNER = register(new BannerBlock("pink_banner", 6, builder() + public static final Block PINK_BANNER = register(new BannerBlock("pink_banner", 6, builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15))); - public static final Block GRAY_BANNER = register(new BannerBlock("gray_banner", 7, builder() + public static final Block GRAY_BANNER = register(new BannerBlock("gray_banner", 7, builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15))); - public static final Block LIGHT_GRAY_BANNER = register(new BannerBlock("light_gray_banner", 8, builder() + public static final Block LIGHT_GRAY_BANNER = register(new BannerBlock("light_gray_banner", 8, builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15))); - public static final Block CYAN_BANNER = register(new BannerBlock("cyan_banner", 9, builder() + public static final Block CYAN_BANNER = register(new BannerBlock("cyan_banner", 9, builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15))); - public static final Block PURPLE_BANNER = register(new BannerBlock("purple_banner", 10, builder() + public static final Block PURPLE_BANNER = register(new BannerBlock("purple_banner", 10, builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15))); - public static final Block BLUE_BANNER = register(new BannerBlock("blue_banner", 11, builder() + public static final Block BLUE_BANNER = register(new BannerBlock("blue_banner", 11, builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15))); - public static final Block BROWN_BANNER = register(new BannerBlock("brown_banner", 12, builder() + public static final Block BROWN_BANNER = register(new BannerBlock("brown_banner", 12, builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15))); - public static final Block GREEN_BANNER = register(new BannerBlock("green_banner", 13, builder() + public static final Block GREEN_BANNER = register(new BannerBlock("green_banner", 13, builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15))); - public static final Block RED_BANNER = register(new BannerBlock("red_banner", 14, builder() + public static final Block RED_BANNER = register(new BannerBlock("red_banner", 14, builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15))); - public static final Block BLACK_BANNER = register(new BannerBlock("black_banner", 15, builder() + public static final Block BLACK_BANNER = register(new BannerBlock("black_banner", 15, builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15))); - public static final Block WHITE_WALL_BANNER = register(new BannerBlock("white_wall_banner", 0, builder() + public static final Block WHITE_WALL_BANNER = register(new BannerBlock("white_wall_banner", 0, builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block ORANGE_WALL_BANNER = register(new BannerBlock("orange_wall_banner", 1, builder() + public static final Block ORANGE_WALL_BANNER = register(new BannerBlock("orange_wall_banner", 1, builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block MAGENTA_WALL_BANNER = register(new BannerBlock("magenta_wall_banner", 2, builder() + public static final Block MAGENTA_WALL_BANNER = register(new BannerBlock("magenta_wall_banner", 2, builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block LIGHT_BLUE_WALL_BANNER = register(new BannerBlock("light_blue_wall_banner", 3, builder() + public static final Block LIGHT_BLUE_WALL_BANNER = register(new BannerBlock("light_blue_wall_banner", 3, builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block YELLOW_WALL_BANNER = register(new BannerBlock("yellow_wall_banner", 4, builder() + public static final Block YELLOW_WALL_BANNER = register(new BannerBlock("yellow_wall_banner", 4, builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block LIME_WALL_BANNER = register(new BannerBlock("lime_wall_banner", 5, builder() + public static final Block LIME_WALL_BANNER = register(new BannerBlock("lime_wall_banner", 5, builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block PINK_WALL_BANNER = register(new BannerBlock("pink_wall_banner", 6, builder() + public static final Block PINK_WALL_BANNER = register(new BannerBlock("pink_wall_banner", 6, builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block GRAY_WALL_BANNER = register(new BannerBlock("gray_wall_banner", 7, builder() + public static final Block GRAY_WALL_BANNER = register(new BannerBlock("gray_wall_banner", 7, builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block LIGHT_GRAY_WALL_BANNER = register(new BannerBlock("light_gray_wall_banner", 8, builder() + public static final Block LIGHT_GRAY_WALL_BANNER = register(new BannerBlock("light_gray_wall_banner", 8, builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block CYAN_WALL_BANNER = register(new BannerBlock("cyan_wall_banner", 9, builder() + public static final Block CYAN_WALL_BANNER = register(new BannerBlock("cyan_wall_banner", 9, builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block PURPLE_WALL_BANNER = register(new BannerBlock("purple_wall_banner", 10, builder() + public static final Block PURPLE_WALL_BANNER = register(new BannerBlock("purple_wall_banner", 10, builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block BLUE_WALL_BANNER = register(new BannerBlock("blue_wall_banner", 11, builder() + public static final Block BLUE_WALL_BANNER = register(new BannerBlock("blue_wall_banner", 11, builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block BROWN_WALL_BANNER = register(new BannerBlock("brown_wall_banner", 12, builder() + public static final Block BROWN_WALL_BANNER = register(new BannerBlock("brown_wall_banner", 12, builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block GREEN_WALL_BANNER = register(new BannerBlock("green_wall_banner", 13, builder() + public static final Block GREEN_WALL_BANNER = register(new BannerBlock("green_wall_banner", 13, builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block RED_WALL_BANNER = register(new BannerBlock("red_wall_banner", 14, builder() + public static final Block RED_WALL_BANNER = register(new BannerBlock("red_wall_banner", 14, builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block BLACK_WALL_BANNER = register(new BannerBlock("black_wall_banner", 15, builder() + public static final Block BLACK_WALL_BANNER = register(new BannerBlock("black_wall_banner", 15, builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block RED_SANDSTONE = register(new Block("red_sandstone", builder())); - public static final Block CHISELED_RED_SANDSTONE = register(new Block("chiseled_red_sandstone", builder())); - public static final Block CUT_RED_SANDSTONE = register(new Block("cut_red_sandstone", builder())); - public static final Block RED_SANDSTONE_STAIRS = register(new Block("red_sandstone_stairs", builder() + public static final Block RED_SANDSTONE = register(new Block("red_sandstone", builder().requiresCorrectToolForDrops().destroyTime(0.8f))); + public static final Block CHISELED_RED_SANDSTONE = register(new Block("chiseled_red_sandstone", builder().requiresCorrectToolForDrops().destroyTime(0.8f))); + public static final Block CUT_RED_SANDSTONE = register(new Block("cut_red_sandstone", builder().requiresCorrectToolForDrops().destroyTime(0.8f))); + public static final Block RED_SANDSTONE_STAIRS = register(new Block("red_sandstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(0.8f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block OAK_SLAB = register(new Block("oak_slab", builder() + public static final Block OAK_SLAB = register(new Block("oak_slab", builder().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block SPRUCE_SLAB = register(new Block("spruce_slab", builder() + public static final Block SPRUCE_SLAB = register(new Block("spruce_slab", builder().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block BIRCH_SLAB = register(new Block("birch_slab", builder() + public static final Block BIRCH_SLAB = register(new Block("birch_slab", builder().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block JUNGLE_SLAB = register(new Block("jungle_slab", builder() + public static final Block JUNGLE_SLAB = register(new Block("jungle_slab", builder().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block ACACIA_SLAB = register(new Block("acacia_slab", builder() + public static final Block ACACIA_SLAB = register(new Block("acacia_slab", builder().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block CHERRY_SLAB = register(new Block("cherry_slab", builder() + public static final Block CHERRY_SLAB = register(new Block("cherry_slab", builder().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block DARK_OAK_SLAB = register(new Block("dark_oak_slab", builder() + public static final Block DARK_OAK_SLAB = register(new Block("dark_oak_slab", builder().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block MANGROVE_SLAB = register(new Block("mangrove_slab", builder() + public static final Block MANGROVE_SLAB = register(new Block("mangrove_slab", builder().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block BAMBOO_SLAB = register(new Block("bamboo_slab", builder() + public static final Block BAMBOO_SLAB = register(new Block("bamboo_slab", builder().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block BAMBOO_MOSAIC_SLAB = register(new Block("bamboo_mosaic_slab", builder() + public static final Block BAMBOO_MOSAIC_SLAB = register(new Block("bamboo_mosaic_slab", builder().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block STONE_SLAB = register(new Block("stone_slab", builder() + public static final Block STONE_SLAB = register(new Block("stone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block SMOOTH_STONE_SLAB = register(new Block("smooth_stone_slab", builder() + public static final Block SMOOTH_STONE_SLAB = register(new Block("smooth_stone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block SANDSTONE_SLAB = register(new Block("sandstone_slab", builder() + public static final Block SANDSTONE_SLAB = register(new Block("sandstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block CUT_SANDSTONE_SLAB = register(new Block("cut_sandstone_slab", builder() + public static final Block CUT_SANDSTONE_SLAB = register(new Block("cut_sandstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block PETRIFIED_OAK_SLAB = register(new Block("petrified_oak_slab", builder() + public static final Block PETRIFIED_OAK_SLAB = register(new Block("petrified_oak_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block COBBLESTONE_SLAB = register(new Block("cobblestone_slab", builder() + public static final Block COBBLESTONE_SLAB = register(new Block("cobblestone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block BRICK_SLAB = register(new Block("brick_slab", builder() + public static final Block BRICK_SLAB = register(new Block("brick_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block STONE_BRICK_SLAB = register(new Block("stone_brick_slab", builder() + public static final Block STONE_BRICK_SLAB = register(new Block("stone_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block MUD_BRICK_SLAB = register(new Block("mud_brick_slab", builder() + public static final Block MUD_BRICK_SLAB = register(new Block("mud_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block NETHER_BRICK_SLAB = register(new Block("nether_brick_slab", builder() + public static final Block NETHER_BRICK_SLAB = register(new Block("nether_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block QUARTZ_SLAB = register(new Block("quartz_slab", builder() + public static final Block QUARTZ_SLAB = register(new Block("quartz_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block RED_SANDSTONE_SLAB = register(new Block("red_sandstone_slab", builder() + public static final Block RED_SANDSTONE_SLAB = register(new Block("red_sandstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block CUT_RED_SANDSTONE_SLAB = register(new Block("cut_red_sandstone_slab", builder() + public static final Block CUT_RED_SANDSTONE_SLAB = register(new Block("cut_red_sandstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block PURPUR_SLAB = register(new Block("purpur_slab", builder() + public static final Block PURPUR_SLAB = register(new Block("purpur_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block SMOOTH_STONE = register(new Block("smooth_stone", builder())); - public static final Block SMOOTH_SANDSTONE = register(new Block("smooth_sandstone", builder())); - public static final Block SMOOTH_QUARTZ = register(new Block("smooth_quartz", builder())); - public static final Block SMOOTH_RED_SANDSTONE = register(new Block("smooth_red_sandstone", builder())); - public static final Block SPRUCE_FENCE_GATE = register(new Block("spruce_fence_gate", builder() + public static final Block SMOOTH_STONE = register(new Block("smooth_stone", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); + public static final Block SMOOTH_SANDSTONE = register(new Block("smooth_sandstone", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); + public static final Block SMOOTH_QUARTZ = register(new Block("smooth_quartz", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); + public static final Block SMOOTH_RED_SANDSTONE = register(new Block("smooth_red_sandstone", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); + public static final Block SPRUCE_FENCE_GATE = register(new Block("spruce_fence_gate", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(IN_WALL) .booleanState(OPEN) .booleanState(POWERED))); - public static final Block BIRCH_FENCE_GATE = register(new Block("birch_fence_gate", builder() + public static final Block BIRCH_FENCE_GATE = register(new Block("birch_fence_gate", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(IN_WALL) .booleanState(OPEN) .booleanState(POWERED))); - public static final Block JUNGLE_FENCE_GATE = register(new Block("jungle_fence_gate", builder() + public static final Block JUNGLE_FENCE_GATE = register(new Block("jungle_fence_gate", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(IN_WALL) .booleanState(OPEN) .booleanState(POWERED))); - public static final Block ACACIA_FENCE_GATE = register(new Block("acacia_fence_gate", builder() + public static final Block ACACIA_FENCE_GATE = register(new Block("acacia_fence_gate", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(IN_WALL) .booleanState(OPEN) .booleanState(POWERED))); - public static final Block CHERRY_FENCE_GATE = register(new Block("cherry_fence_gate", builder() + public static final Block CHERRY_FENCE_GATE = register(new Block("cherry_fence_gate", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(IN_WALL) .booleanState(OPEN) .booleanState(POWERED))); - public static final Block DARK_OAK_FENCE_GATE = register(new Block("dark_oak_fence_gate", builder() + public static final Block DARK_OAK_FENCE_GATE = register(new Block("dark_oak_fence_gate", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(IN_WALL) .booleanState(OPEN) .booleanState(POWERED))); - public static final Block MANGROVE_FENCE_GATE = register(new Block("mangrove_fence_gate", builder() + public static final Block MANGROVE_FENCE_GATE = register(new Block("mangrove_fence_gate", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(IN_WALL) .booleanState(OPEN) .booleanState(POWERED))); - public static final Block BAMBOO_FENCE_GATE = register(new Block("bamboo_fence_gate", builder() + public static final Block BAMBOO_FENCE_GATE = register(new Block("bamboo_fence_gate", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(IN_WALL) .booleanState(OPEN) .booleanState(POWERED))); - public static final Block SPRUCE_FENCE = register(new Block("spruce_fence", builder() + public static final Block SPRUCE_FENCE = register(new Block("spruce_fence", builder().destroyTime(2.0f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block BIRCH_FENCE = register(new Block("birch_fence", builder() + public static final Block BIRCH_FENCE = register(new Block("birch_fence", builder().destroyTime(2.0f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block JUNGLE_FENCE = register(new Block("jungle_fence", builder() + public static final Block JUNGLE_FENCE = register(new Block("jungle_fence", builder().destroyTime(2.0f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block ACACIA_FENCE = register(new Block("acacia_fence", builder() + public static final Block ACACIA_FENCE = register(new Block("acacia_fence", builder().destroyTime(2.0f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block CHERRY_FENCE = register(new Block("cherry_fence", builder() + public static final Block CHERRY_FENCE = register(new Block("cherry_fence", builder().destroyTime(2.0f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block DARK_OAK_FENCE = register(new Block("dark_oak_fence", builder() + public static final Block DARK_OAK_FENCE = register(new Block("dark_oak_fence", builder().destroyTime(2.0f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block MANGROVE_FENCE = register(new Block("mangrove_fence", builder() + public static final Block MANGROVE_FENCE = register(new Block("mangrove_fence", builder().destroyTime(2.0f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block BAMBOO_FENCE = register(new Block("bamboo_fence", builder() + public static final Block BAMBOO_FENCE = register(new Block("bamboo_fence", builder().destroyTime(2.0f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block SPRUCE_DOOR = register(new Block("spruce_door", builder() + public static final Block SPRUCE_DOOR = register(new Block("spruce_door", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block BIRCH_DOOR = register(new Block("birch_door", builder() + public static final Block BIRCH_DOOR = register(new Block("birch_door", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block JUNGLE_DOOR = register(new Block("jungle_door", builder() + public static final Block JUNGLE_DOOR = register(new Block("jungle_door", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block ACACIA_DOOR = register(new Block("acacia_door", builder() + public static final Block ACACIA_DOOR = register(new Block("acacia_door", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block CHERRY_DOOR = register(new Block("cherry_door", builder() + public static final Block CHERRY_DOOR = register(new Block("cherry_door", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block DARK_OAK_DOOR = register(new Block("dark_oak_door", builder() + public static final Block DARK_OAK_DOOR = register(new Block("dark_oak_door", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block MANGROVE_DOOR = register(new Block("mangrove_door", builder() + public static final Block MANGROVE_DOOR = register(new Block("mangrove_door", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block BAMBOO_DOOR = register(new Block("bamboo_door", builder() + public static final Block BAMBOO_DOOR = register(new Block("bamboo_door", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") @@ -1548,24 +1548,24 @@ public final class Blocks { .booleanState(POWERED))); public static final Block END_ROD = register(new Block("end_rod", builder() .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block CHORUS_PLANT = register(new Block("chorus_plant", builder() + public static final Block CHORUS_PLANT = register(new Block("chorus_plant", builder().destroyTime(0.4f) .booleanState(DOWN) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(UP) .booleanState(WEST))); - public static final Block CHORUS_FLOWER = register(new Block("chorus_flower", builder() + public static final Block CHORUS_FLOWER = register(new Block("chorus_flower", builder().destroyTime(0.4f) .intState(AGE_5, 0, 5))); - public static final Block PURPUR_BLOCK = register(new Block("purpur_block", builder())); - public static final Block PURPUR_PILLAR = register(new Block("purpur_pillar", builder() + public static final Block PURPUR_BLOCK = register(new Block("purpur_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block PURPUR_PILLAR = register(new Block("purpur_pillar", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(AXIS, Axis.VALUES))); - public static final Block PURPUR_STAIRS = register(new Block("purpur_stairs", builder() + public static final Block PURPUR_STAIRS = register(new Block("purpur_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block END_STONE_BRICKS = register(new Block("end_stone_bricks", builder())); + public static final Block END_STONE_BRICKS = register(new Block("end_stone_bricks", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); public static final Block TORCHFLOWER_CROP = register(new Block("torchflower_crop", builder() .intState(AGE_1, 0, 1))); public static final Block PITCHER_CROP = register(new Block("pitcher_crop", builder() @@ -1575,151 +1575,151 @@ public final class Blocks { .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); public static final Block BEETROOTS = register(new Block("beetroots", builder() .intState(AGE_3, 0, 3))); - public static final Block DIRT_PATH = register(new Block("dirt_path", builder())); - public static final Block END_GATEWAY = register(new Block("end_gateway", builder())); - public static final Block REPEATING_COMMAND_BLOCK = register(new Block("repeating_command_block", builder() + public static final Block DIRT_PATH = register(new Block("dirt_path", builder().destroyTime(0.65f))); + public static final Block END_GATEWAY = register(new Block("end_gateway", builder().setBlockEntity().destroyTime(-1.0f))); + public static final Block REPEATING_COMMAND_BLOCK = register(new Block("repeating_command_block", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(-1.0f) .booleanState(CONDITIONAL) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block CHAIN_COMMAND_BLOCK = register(new Block("chain_command_block", builder() + public static final Block CHAIN_COMMAND_BLOCK = register(new Block("chain_command_block", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(-1.0f) .booleanState(CONDITIONAL) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block FROSTED_ICE = register(new Block("frosted_ice", builder() + public static final Block FROSTED_ICE = register(new Block("frosted_ice", builder().destroyTime(0.5f) .intState(AGE_3, 0, 3))); - public static final Block MAGMA_BLOCK = register(new Block("magma_block", builder())); - public static final Block NETHER_WART_BLOCK = register(new Block("nether_wart_block", builder())); - public static final Block RED_NETHER_BRICKS = register(new Block("red_nether_bricks", builder())); - public static final Block BONE_BLOCK = register(new Block("bone_block", builder() + public static final Block MAGMA_BLOCK = register(new Block("magma_block", builder().requiresCorrectToolForDrops().destroyTime(0.5f))); + public static final Block NETHER_WART_BLOCK = register(new Block("nether_wart_block", builder().destroyTime(1.0f))); + public static final Block RED_NETHER_BRICKS = register(new Block("red_nether_bricks", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); + public static final Block BONE_BLOCK = register(new Block("bone_block", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); public static final Block STRUCTURE_VOID = register(new Block("structure_void", builder())); - public static final Block OBSERVER = register(new Block("observer", builder() + public static final Block OBSERVER = register(new Block("observer", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .booleanState(POWERED))); - public static final Block SHULKER_BOX = register(new Block("shulker_box", builder() + public static final Block SHULKER_BOX = register(new Block("shulker_box", builder().setBlockEntity().destroyTime(2.0f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block WHITE_SHULKER_BOX = register(new Block("white_shulker_box", builder() + public static final Block WHITE_SHULKER_BOX = register(new Block("white_shulker_box", builder().setBlockEntity().destroyTime(2.0f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block ORANGE_SHULKER_BOX = register(new Block("orange_shulker_box", builder() + public static final Block ORANGE_SHULKER_BOX = register(new Block("orange_shulker_box", builder().setBlockEntity().destroyTime(2.0f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block MAGENTA_SHULKER_BOX = register(new Block("magenta_shulker_box", builder() + public static final Block MAGENTA_SHULKER_BOX = register(new Block("magenta_shulker_box", builder().setBlockEntity().destroyTime(2.0f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block LIGHT_BLUE_SHULKER_BOX = register(new Block("light_blue_shulker_box", builder() + public static final Block LIGHT_BLUE_SHULKER_BOX = register(new Block("light_blue_shulker_box", builder().setBlockEntity().destroyTime(2.0f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block YELLOW_SHULKER_BOX = register(new Block("yellow_shulker_box", builder() + public static final Block YELLOW_SHULKER_BOX = register(new Block("yellow_shulker_box", builder().setBlockEntity().destroyTime(2.0f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block LIME_SHULKER_BOX = register(new Block("lime_shulker_box", builder() + public static final Block LIME_SHULKER_BOX = register(new Block("lime_shulker_box", builder().setBlockEntity().destroyTime(2.0f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block PINK_SHULKER_BOX = register(new Block("pink_shulker_box", builder() + public static final Block PINK_SHULKER_BOX = register(new Block("pink_shulker_box", builder().setBlockEntity().destroyTime(2.0f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block GRAY_SHULKER_BOX = register(new Block("gray_shulker_box", builder() + public static final Block GRAY_SHULKER_BOX = register(new Block("gray_shulker_box", builder().setBlockEntity().destroyTime(2.0f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block LIGHT_GRAY_SHULKER_BOX = register(new Block("light_gray_shulker_box", builder() + public static final Block LIGHT_GRAY_SHULKER_BOX = register(new Block("light_gray_shulker_box", builder().setBlockEntity().destroyTime(2.0f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block CYAN_SHULKER_BOX = register(new Block("cyan_shulker_box", builder() + public static final Block CYAN_SHULKER_BOX = register(new Block("cyan_shulker_box", builder().setBlockEntity().destroyTime(2.0f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block PURPLE_SHULKER_BOX = register(new Block("purple_shulker_box", builder() + public static final Block PURPLE_SHULKER_BOX = register(new Block("purple_shulker_box", builder().setBlockEntity().destroyTime(2.0f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block BLUE_SHULKER_BOX = register(new Block("blue_shulker_box", builder() + public static final Block BLUE_SHULKER_BOX = register(new Block("blue_shulker_box", builder().setBlockEntity().destroyTime(2.0f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block BROWN_SHULKER_BOX = register(new Block("brown_shulker_box", builder() + public static final Block BROWN_SHULKER_BOX = register(new Block("brown_shulker_box", builder().setBlockEntity().destroyTime(2.0f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block GREEN_SHULKER_BOX = register(new Block("green_shulker_box", builder() + public static final Block GREEN_SHULKER_BOX = register(new Block("green_shulker_box", builder().setBlockEntity().destroyTime(2.0f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block RED_SHULKER_BOX = register(new Block("red_shulker_box", builder() + public static final Block RED_SHULKER_BOX = register(new Block("red_shulker_box", builder().setBlockEntity().destroyTime(2.0f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block BLACK_SHULKER_BOX = register(new Block("black_shulker_box", builder() + public static final Block BLACK_SHULKER_BOX = register(new Block("black_shulker_box", builder().setBlockEntity().destroyTime(2.0f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block WHITE_GLAZED_TERRACOTTA = register(new Block("white_glazed_terracotta", builder() + public static final Block WHITE_GLAZED_TERRACOTTA = register(new Block("white_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block ORANGE_GLAZED_TERRACOTTA = register(new Block("orange_glazed_terracotta", builder() + public static final Block ORANGE_GLAZED_TERRACOTTA = register(new Block("orange_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block MAGENTA_GLAZED_TERRACOTTA = register(new Block("magenta_glazed_terracotta", builder() + public static final Block MAGENTA_GLAZED_TERRACOTTA = register(new Block("magenta_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block LIGHT_BLUE_GLAZED_TERRACOTTA = register(new Block("light_blue_glazed_terracotta", builder() + public static final Block LIGHT_BLUE_GLAZED_TERRACOTTA = register(new Block("light_blue_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block YELLOW_GLAZED_TERRACOTTA = register(new Block("yellow_glazed_terracotta", builder() + public static final Block YELLOW_GLAZED_TERRACOTTA = register(new Block("yellow_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block LIME_GLAZED_TERRACOTTA = register(new Block("lime_glazed_terracotta", builder() + public static final Block LIME_GLAZED_TERRACOTTA = register(new Block("lime_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block PINK_GLAZED_TERRACOTTA = register(new Block("pink_glazed_terracotta", builder() + public static final Block PINK_GLAZED_TERRACOTTA = register(new Block("pink_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block GRAY_GLAZED_TERRACOTTA = register(new Block("gray_glazed_terracotta", builder() + public static final Block GRAY_GLAZED_TERRACOTTA = register(new Block("gray_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block LIGHT_GRAY_GLAZED_TERRACOTTA = register(new Block("light_gray_glazed_terracotta", builder() + public static final Block LIGHT_GRAY_GLAZED_TERRACOTTA = register(new Block("light_gray_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block CYAN_GLAZED_TERRACOTTA = register(new Block("cyan_glazed_terracotta", builder() + public static final Block CYAN_GLAZED_TERRACOTTA = register(new Block("cyan_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block PURPLE_GLAZED_TERRACOTTA = register(new Block("purple_glazed_terracotta", builder() + public static final Block PURPLE_GLAZED_TERRACOTTA = register(new Block("purple_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block BLUE_GLAZED_TERRACOTTA = register(new Block("blue_glazed_terracotta", builder() + public static final Block BLUE_GLAZED_TERRACOTTA = register(new Block("blue_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block BROWN_GLAZED_TERRACOTTA = register(new Block("brown_glazed_terracotta", builder() + public static final Block BROWN_GLAZED_TERRACOTTA = register(new Block("brown_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block GREEN_GLAZED_TERRACOTTA = register(new Block("green_glazed_terracotta", builder() + public static final Block GREEN_GLAZED_TERRACOTTA = register(new Block("green_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block RED_GLAZED_TERRACOTTA = register(new Block("red_glazed_terracotta", builder() + public static final Block RED_GLAZED_TERRACOTTA = register(new Block("red_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block BLACK_GLAZED_TERRACOTTA = register(new Block("black_glazed_terracotta", builder() + public static final Block BLACK_GLAZED_TERRACOTTA = register(new Block("black_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block WHITE_CONCRETE = register(new Block("white_concrete", builder())); - public static final Block ORANGE_CONCRETE = register(new Block("orange_concrete", builder())); - public static final Block MAGENTA_CONCRETE = register(new Block("magenta_concrete", builder())); - public static final Block LIGHT_BLUE_CONCRETE = register(new Block("light_blue_concrete", builder())); - public static final Block YELLOW_CONCRETE = register(new Block("yellow_concrete", builder())); - public static final Block LIME_CONCRETE = register(new Block("lime_concrete", builder())); - public static final Block PINK_CONCRETE = register(new Block("pink_concrete", builder())); - public static final Block GRAY_CONCRETE = register(new Block("gray_concrete", builder())); - public static final Block LIGHT_GRAY_CONCRETE = register(new Block("light_gray_concrete", builder())); - public static final Block CYAN_CONCRETE = register(new Block("cyan_concrete", builder())); - public static final Block PURPLE_CONCRETE = register(new Block("purple_concrete", builder())); - public static final Block BLUE_CONCRETE = register(new Block("blue_concrete", builder())); - public static final Block BROWN_CONCRETE = register(new Block("brown_concrete", builder())); - public static final Block GREEN_CONCRETE = register(new Block("green_concrete", builder())); - public static final Block RED_CONCRETE = register(new Block("red_concrete", builder())); - public static final Block BLACK_CONCRETE = register(new Block("black_concrete", builder())); - public static final Block WHITE_CONCRETE_POWDER = register(new Block("white_concrete_powder", builder())); - public static final Block ORANGE_CONCRETE_POWDER = register(new Block("orange_concrete_powder", builder())); - public static final Block MAGENTA_CONCRETE_POWDER = register(new Block("magenta_concrete_powder", builder())); - public static final Block LIGHT_BLUE_CONCRETE_POWDER = register(new Block("light_blue_concrete_powder", builder())); - public static final Block YELLOW_CONCRETE_POWDER = register(new Block("yellow_concrete_powder", builder())); - public static final Block LIME_CONCRETE_POWDER = register(new Block("lime_concrete_powder", builder())); - public static final Block PINK_CONCRETE_POWDER = register(new Block("pink_concrete_powder", builder())); - public static final Block GRAY_CONCRETE_POWDER = register(new Block("gray_concrete_powder", builder())); - public static final Block LIGHT_GRAY_CONCRETE_POWDER = register(new Block("light_gray_concrete_powder", builder())); - public static final Block CYAN_CONCRETE_POWDER = register(new Block("cyan_concrete_powder", builder())); - public static final Block PURPLE_CONCRETE_POWDER = register(new Block("purple_concrete_powder", builder())); - public static final Block BLUE_CONCRETE_POWDER = register(new Block("blue_concrete_powder", builder())); - public static final Block BROWN_CONCRETE_POWDER = register(new Block("brown_concrete_powder", builder())); - public static final Block GREEN_CONCRETE_POWDER = register(new Block("green_concrete_powder", builder())); - public static final Block RED_CONCRETE_POWDER = register(new Block("red_concrete_powder", builder())); - public static final Block BLACK_CONCRETE_POWDER = register(new Block("black_concrete_powder", builder())); + public static final Block WHITE_CONCRETE = register(new Block("white_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f))); + public static final Block ORANGE_CONCRETE = register(new Block("orange_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f))); + public static final Block MAGENTA_CONCRETE = register(new Block("magenta_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f))); + public static final Block LIGHT_BLUE_CONCRETE = register(new Block("light_blue_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f))); + public static final Block YELLOW_CONCRETE = register(new Block("yellow_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f))); + public static final Block LIME_CONCRETE = register(new Block("lime_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f))); + public static final Block PINK_CONCRETE = register(new Block("pink_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f))); + public static final Block GRAY_CONCRETE = register(new Block("gray_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f))); + public static final Block LIGHT_GRAY_CONCRETE = register(new Block("light_gray_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f))); + public static final Block CYAN_CONCRETE = register(new Block("cyan_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f))); + public static final Block PURPLE_CONCRETE = register(new Block("purple_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f))); + public static final Block BLUE_CONCRETE = register(new Block("blue_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f))); + public static final Block BROWN_CONCRETE = register(new Block("brown_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f))); + public static final Block GREEN_CONCRETE = register(new Block("green_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f))); + public static final Block RED_CONCRETE = register(new Block("red_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f))); + public static final Block BLACK_CONCRETE = register(new Block("black_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f))); + public static final Block WHITE_CONCRETE_POWDER = register(new Block("white_concrete_powder", builder().destroyTime(0.5f))); + public static final Block ORANGE_CONCRETE_POWDER = register(new Block("orange_concrete_powder", builder().destroyTime(0.5f))); + public static final Block MAGENTA_CONCRETE_POWDER = register(new Block("magenta_concrete_powder", builder().destroyTime(0.5f))); + public static final Block LIGHT_BLUE_CONCRETE_POWDER = register(new Block("light_blue_concrete_powder", builder().destroyTime(0.5f))); + public static final Block YELLOW_CONCRETE_POWDER = register(new Block("yellow_concrete_powder", builder().destroyTime(0.5f))); + public static final Block LIME_CONCRETE_POWDER = register(new Block("lime_concrete_powder", builder().destroyTime(0.5f))); + public static final Block PINK_CONCRETE_POWDER = register(new Block("pink_concrete_powder", builder().destroyTime(0.5f))); + public static final Block GRAY_CONCRETE_POWDER = register(new Block("gray_concrete_powder", builder().destroyTime(0.5f))); + public static final Block LIGHT_GRAY_CONCRETE_POWDER = register(new Block("light_gray_concrete_powder", builder().destroyTime(0.5f))); + public static final Block CYAN_CONCRETE_POWDER = register(new Block("cyan_concrete_powder", builder().destroyTime(0.5f))); + public static final Block PURPLE_CONCRETE_POWDER = register(new Block("purple_concrete_powder", builder().destroyTime(0.5f))); + public static final Block BLUE_CONCRETE_POWDER = register(new Block("blue_concrete_powder", builder().destroyTime(0.5f))); + public static final Block BROWN_CONCRETE_POWDER = register(new Block("brown_concrete_powder", builder().destroyTime(0.5f))); + public static final Block GREEN_CONCRETE_POWDER = register(new Block("green_concrete_powder", builder().destroyTime(0.5f))); + public static final Block RED_CONCRETE_POWDER = register(new Block("red_concrete_powder", builder().destroyTime(0.5f))); + public static final Block BLACK_CONCRETE_POWDER = register(new Block("black_concrete_powder", builder().destroyTime(0.5f))); public static final Block KELP = register(new Block("kelp", builder() .intState(AGE_25, 0, 25))); public static final Block KELP_PLANT = register(new Block("kelp_plant", builder())); - public static final Block DRIED_KELP_BLOCK = register(new Block("dried_kelp_block", builder())); - public static final Block TURTLE_EGG = register(new Block("turtle_egg", builder() + public static final Block DRIED_KELP_BLOCK = register(new Block("dried_kelp_block", builder().destroyTime(0.5f))); + public static final Block TURTLE_EGG = register(new Block("turtle_egg", builder().destroyTime(0.5f) .intState(EGGS, 1, 4) .intState(HATCH, 0, 2))); - public static final Block SNIFFER_EGG = register(new Block("sniffer_egg", builder() + public static final Block SNIFFER_EGG = register(new Block("sniffer_egg", builder().destroyTime(0.5f) .intState(HATCH, 0, 2))); - public static final Block DEAD_TUBE_CORAL_BLOCK = register(new Block("dead_tube_coral_block", builder())); - public static final Block DEAD_BRAIN_CORAL_BLOCK = register(new Block("dead_brain_coral_block", builder())); - public static final Block DEAD_BUBBLE_CORAL_BLOCK = register(new Block("dead_bubble_coral_block", builder())); - public static final Block DEAD_FIRE_CORAL_BLOCK = register(new Block("dead_fire_coral_block", builder())); - public static final Block DEAD_HORN_CORAL_BLOCK = register(new Block("dead_horn_coral_block", builder())); - public static final Block TUBE_CORAL_BLOCK = register(new Block("tube_coral_block", builder())); - public static final Block BRAIN_CORAL_BLOCK = register(new Block("brain_coral_block", builder())); - public static final Block BUBBLE_CORAL_BLOCK = register(new Block("bubble_coral_block", builder())); - public static final Block FIRE_CORAL_BLOCK = register(new Block("fire_coral_block", builder())); - public static final Block HORN_CORAL_BLOCK = register(new Block("horn_coral_block", builder())); - public static final Block DEAD_TUBE_CORAL = register(new Block("dead_tube_coral", builder() + public static final Block DEAD_TUBE_CORAL_BLOCK = register(new Block("dead_tube_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block DEAD_BRAIN_CORAL_BLOCK = register(new Block("dead_brain_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block DEAD_BUBBLE_CORAL_BLOCK = register(new Block("dead_bubble_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block DEAD_FIRE_CORAL_BLOCK = register(new Block("dead_fire_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block DEAD_HORN_CORAL_BLOCK = register(new Block("dead_horn_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block TUBE_CORAL_BLOCK = register(new Block("tube_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block BRAIN_CORAL_BLOCK = register(new Block("brain_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block BUBBLE_CORAL_BLOCK = register(new Block("bubble_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block FIRE_CORAL_BLOCK = register(new Block("fire_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block HORN_CORAL_BLOCK = register(new Block("horn_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block DEAD_TUBE_CORAL = register(new Block("dead_tube_coral", builder().requiresCorrectToolForDrops() .booleanState(WATERLOGGED))); - public static final Block DEAD_BRAIN_CORAL = register(new Block("dead_brain_coral", builder() + public static final Block DEAD_BRAIN_CORAL = register(new Block("dead_brain_coral", builder().requiresCorrectToolForDrops() .booleanState(WATERLOGGED))); - public static final Block DEAD_BUBBLE_CORAL = register(new Block("dead_bubble_coral", builder() + public static final Block DEAD_BUBBLE_CORAL = register(new Block("dead_bubble_coral", builder().requiresCorrectToolForDrops() .booleanState(WATERLOGGED))); - public static final Block DEAD_FIRE_CORAL = register(new Block("dead_fire_coral", builder() + public static final Block DEAD_FIRE_CORAL = register(new Block("dead_fire_coral", builder().requiresCorrectToolForDrops() .booleanState(WATERLOGGED))); - public static final Block DEAD_HORN_CORAL = register(new Block("dead_horn_coral", builder() + public static final Block DEAD_HORN_CORAL = register(new Block("dead_horn_coral", builder().requiresCorrectToolForDrops() .booleanState(WATERLOGGED))); public static final Block TUBE_CORAL = register(new Block("tube_coral", builder() .booleanState(WATERLOGGED))); @@ -1731,15 +1731,15 @@ public final class Blocks { .booleanState(WATERLOGGED))); public static final Block HORN_CORAL = register(new Block("horn_coral", builder() .booleanState(WATERLOGGED))); - public static final Block DEAD_TUBE_CORAL_FAN = register(new Block("dead_tube_coral_fan", builder() + public static final Block DEAD_TUBE_CORAL_FAN = register(new Block("dead_tube_coral_fan", builder().requiresCorrectToolForDrops() .booleanState(WATERLOGGED))); - public static final Block DEAD_BRAIN_CORAL_FAN = register(new Block("dead_brain_coral_fan", builder() + public static final Block DEAD_BRAIN_CORAL_FAN = register(new Block("dead_brain_coral_fan", builder().requiresCorrectToolForDrops() .booleanState(WATERLOGGED))); - public static final Block DEAD_BUBBLE_CORAL_FAN = register(new Block("dead_bubble_coral_fan", builder() + public static final Block DEAD_BUBBLE_CORAL_FAN = register(new Block("dead_bubble_coral_fan", builder().requiresCorrectToolForDrops() .booleanState(WATERLOGGED))); - public static final Block DEAD_FIRE_CORAL_FAN = register(new Block("dead_fire_coral_fan", builder() + public static final Block DEAD_FIRE_CORAL_FAN = register(new Block("dead_fire_coral_fan", builder().requiresCorrectToolForDrops() .booleanState(WATERLOGGED))); - public static final Block DEAD_HORN_CORAL_FAN = register(new Block("dead_horn_coral_fan", builder() + public static final Block DEAD_HORN_CORAL_FAN = register(new Block("dead_horn_coral_fan", builder().requiresCorrectToolForDrops() .booleanState(WATERLOGGED))); public static final Block TUBE_CORAL_FAN = register(new Block("tube_coral_fan", builder() .booleanState(WATERLOGGED))); @@ -1751,19 +1751,19 @@ public final class Blocks { .booleanState(WATERLOGGED))); public static final Block HORN_CORAL_FAN = register(new Block("horn_coral_fan", builder() .booleanState(WATERLOGGED))); - public static final Block DEAD_TUBE_CORAL_WALL_FAN = register(new Block("dead_tube_coral_wall_fan", builder() + public static final Block DEAD_TUBE_CORAL_WALL_FAN = register(new Block("dead_tube_coral_wall_fan", builder().requiresCorrectToolForDrops() .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block DEAD_BRAIN_CORAL_WALL_FAN = register(new Block("dead_brain_coral_wall_fan", builder() + public static final Block DEAD_BRAIN_CORAL_WALL_FAN = register(new Block("dead_brain_coral_wall_fan", builder().requiresCorrectToolForDrops() .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block DEAD_BUBBLE_CORAL_WALL_FAN = register(new Block("dead_bubble_coral_wall_fan", builder() + public static final Block DEAD_BUBBLE_CORAL_WALL_FAN = register(new Block("dead_bubble_coral_wall_fan", builder().requiresCorrectToolForDrops() .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block DEAD_FIRE_CORAL_WALL_FAN = register(new Block("dead_fire_coral_wall_fan", builder() + public static final Block DEAD_FIRE_CORAL_WALL_FAN = register(new Block("dead_fire_coral_wall_fan", builder().requiresCorrectToolForDrops() .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block DEAD_HORN_CORAL_WALL_FAN = register(new Block("dead_horn_coral_wall_fan", builder() + public static final Block DEAD_HORN_CORAL_WALL_FAN = register(new Block("dead_horn_coral_wall_fan", builder().requiresCorrectToolForDrops() .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); public static final Block TUBE_CORAL_WALL_FAN = register(new Block("tube_coral_wall_fan", builder() @@ -1784,11 +1784,11 @@ public final class Blocks { public static final Block SEA_PICKLE = register(new Block("sea_pickle", builder() .intState(PICKLES, 1, 4) .booleanState(WATERLOGGED))); - public static final Block BLUE_ICE = register(new Block("blue_ice", builder())); - public static final Block CONDUIT = register(new Block("conduit", builder() + public static final Block BLUE_ICE = register(new Block("blue_ice", builder().destroyTime(2.8f))); + public static final Block CONDUIT = register(new Block("conduit", builder().setBlockEntity().destroyTime(3.0f) .booleanState(WATERLOGGED))); - public static final Block BAMBOO_SAPLING = register(new Block("bamboo_sapling", builder())); - public static final Block BAMBOO = register(new Block("bamboo", builder() + public static final Block BAMBOO_SAPLING = register(new Block("bamboo_sapling", builder().destroyTime(1.0f))); + public static final Block BAMBOO = register(new Block("bamboo", builder().destroyTime(1.0f) .intState(AGE_1, 0, 1) .enumState(BAMBOO_LEAVES, "none", "small", "large") .intState(STAGE, 0, 1))); @@ -1797,200 +1797,200 @@ public final class Blocks { public static final Block CAVE_AIR = register(new Block("cave_air", builder())); public static final Block BUBBLE_COLUMN = register(new Block("bubble_column", builder() .booleanState(DRAG))); - public static final Block POLISHED_GRANITE_STAIRS = register(new Block("polished_granite_stairs", builder() + public static final Block POLISHED_GRANITE_STAIRS = register(new Block("polished_granite_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block SMOOTH_RED_SANDSTONE_STAIRS = register(new Block("smooth_red_sandstone_stairs", builder() + public static final Block SMOOTH_RED_SANDSTONE_STAIRS = register(new Block("smooth_red_sandstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block MOSSY_STONE_BRICK_STAIRS = register(new Block("mossy_stone_brick_stairs", builder() + public static final Block MOSSY_STONE_BRICK_STAIRS = register(new Block("mossy_stone_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block POLISHED_DIORITE_STAIRS = register(new Block("polished_diorite_stairs", builder() + public static final Block POLISHED_DIORITE_STAIRS = register(new Block("polished_diorite_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block MOSSY_COBBLESTONE_STAIRS = register(new Block("mossy_cobblestone_stairs", builder() + public static final Block MOSSY_COBBLESTONE_STAIRS = register(new Block("mossy_cobblestone_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block END_STONE_BRICK_STAIRS = register(new Block("end_stone_brick_stairs", builder() + public static final Block END_STONE_BRICK_STAIRS = register(new Block("end_stone_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block STONE_STAIRS = register(new Block("stone_stairs", builder() + public static final Block STONE_STAIRS = register(new Block("stone_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block SMOOTH_SANDSTONE_STAIRS = register(new Block("smooth_sandstone_stairs", builder() + public static final Block SMOOTH_SANDSTONE_STAIRS = register(new Block("smooth_sandstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block SMOOTH_QUARTZ_STAIRS = register(new Block("smooth_quartz_stairs", builder() + public static final Block SMOOTH_QUARTZ_STAIRS = register(new Block("smooth_quartz_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block GRANITE_STAIRS = register(new Block("granite_stairs", builder() + public static final Block GRANITE_STAIRS = register(new Block("granite_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block ANDESITE_STAIRS = register(new Block("andesite_stairs", builder() + public static final Block ANDESITE_STAIRS = register(new Block("andesite_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block RED_NETHER_BRICK_STAIRS = register(new Block("red_nether_brick_stairs", builder() + public static final Block RED_NETHER_BRICK_STAIRS = register(new Block("red_nether_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block POLISHED_ANDESITE_STAIRS = register(new Block("polished_andesite_stairs", builder() + public static final Block POLISHED_ANDESITE_STAIRS = register(new Block("polished_andesite_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block DIORITE_STAIRS = register(new Block("diorite_stairs", builder() + public static final Block DIORITE_STAIRS = register(new Block("diorite_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block POLISHED_GRANITE_SLAB = register(new Block("polished_granite_slab", builder() + public static final Block POLISHED_GRANITE_SLAB = register(new Block("polished_granite_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block SMOOTH_RED_SANDSTONE_SLAB = register(new Block("smooth_red_sandstone_slab", builder() + public static final Block SMOOTH_RED_SANDSTONE_SLAB = register(new Block("smooth_red_sandstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block MOSSY_STONE_BRICK_SLAB = register(new Block("mossy_stone_brick_slab", builder() + public static final Block MOSSY_STONE_BRICK_SLAB = register(new Block("mossy_stone_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block POLISHED_DIORITE_SLAB = register(new Block("polished_diorite_slab", builder() + public static final Block POLISHED_DIORITE_SLAB = register(new Block("polished_diorite_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block MOSSY_COBBLESTONE_SLAB = register(new Block("mossy_cobblestone_slab", builder() + public static final Block MOSSY_COBBLESTONE_SLAB = register(new Block("mossy_cobblestone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block END_STONE_BRICK_SLAB = register(new Block("end_stone_brick_slab", builder() + public static final Block END_STONE_BRICK_SLAB = register(new Block("end_stone_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block SMOOTH_SANDSTONE_SLAB = register(new Block("smooth_sandstone_slab", builder() + public static final Block SMOOTH_SANDSTONE_SLAB = register(new Block("smooth_sandstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block SMOOTH_QUARTZ_SLAB = register(new Block("smooth_quartz_slab", builder() + public static final Block SMOOTH_QUARTZ_SLAB = register(new Block("smooth_quartz_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block GRANITE_SLAB = register(new Block("granite_slab", builder() + public static final Block GRANITE_SLAB = register(new Block("granite_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block ANDESITE_SLAB = register(new Block("andesite_slab", builder() + public static final Block ANDESITE_SLAB = register(new Block("andesite_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block RED_NETHER_BRICK_SLAB = register(new Block("red_nether_brick_slab", builder() + public static final Block RED_NETHER_BRICK_SLAB = register(new Block("red_nether_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block POLISHED_ANDESITE_SLAB = register(new Block("polished_andesite_slab", builder() + public static final Block POLISHED_ANDESITE_SLAB = register(new Block("polished_andesite_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block DIORITE_SLAB = register(new Block("diorite_slab", builder() + public static final Block DIORITE_SLAB = register(new Block("diorite_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block BRICK_WALL = register(new Block("brick_wall", builder() + public static final Block BRICK_WALL = register(new Block("brick_wall", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(EAST_WALL, "none", "low", "tall") .enumState(NORTH_WALL, "none", "low", "tall") .enumState(SOUTH_WALL, "none", "low", "tall") .booleanState(UP) .booleanState(WATERLOGGED) .enumState(WEST_WALL, "none", "low", "tall"))); - public static final Block PRISMARINE_WALL = register(new Block("prismarine_wall", builder() + public static final Block PRISMARINE_WALL = register(new Block("prismarine_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(EAST_WALL, "none", "low", "tall") .enumState(NORTH_WALL, "none", "low", "tall") .enumState(SOUTH_WALL, "none", "low", "tall") .booleanState(UP) .booleanState(WATERLOGGED) .enumState(WEST_WALL, "none", "low", "tall"))); - public static final Block RED_SANDSTONE_WALL = register(new Block("red_sandstone_wall", builder() + public static final Block RED_SANDSTONE_WALL = register(new Block("red_sandstone_wall", builder().requiresCorrectToolForDrops().destroyTime(0.8f) .enumState(EAST_WALL, "none", "low", "tall") .enumState(NORTH_WALL, "none", "low", "tall") .enumState(SOUTH_WALL, "none", "low", "tall") .booleanState(UP) .booleanState(WATERLOGGED) .enumState(WEST_WALL, "none", "low", "tall"))); - public static final Block MOSSY_STONE_BRICK_WALL = register(new Block("mossy_stone_brick_wall", builder() + public static final Block MOSSY_STONE_BRICK_WALL = register(new Block("mossy_stone_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(EAST_WALL, "none", "low", "tall") .enumState(NORTH_WALL, "none", "low", "tall") .enumState(SOUTH_WALL, "none", "low", "tall") .booleanState(UP) .booleanState(WATERLOGGED) .enumState(WEST_WALL, "none", "low", "tall"))); - public static final Block GRANITE_WALL = register(new Block("granite_wall", builder() + public static final Block GRANITE_WALL = register(new Block("granite_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(EAST_WALL, "none", "low", "tall") .enumState(NORTH_WALL, "none", "low", "tall") .enumState(SOUTH_WALL, "none", "low", "tall") .booleanState(UP) .booleanState(WATERLOGGED) .enumState(WEST_WALL, "none", "low", "tall"))); - public static final Block STONE_BRICK_WALL = register(new Block("stone_brick_wall", builder() + public static final Block STONE_BRICK_WALL = register(new Block("stone_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(EAST_WALL, "none", "low", "tall") .enumState(NORTH_WALL, "none", "low", "tall") .enumState(SOUTH_WALL, "none", "low", "tall") .booleanState(UP) .booleanState(WATERLOGGED) .enumState(WEST_WALL, "none", "low", "tall"))); - public static final Block MUD_BRICK_WALL = register(new Block("mud_brick_wall", builder() + public static final Block MUD_BRICK_WALL = register(new Block("mud_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(EAST_WALL, "none", "low", "tall") .enumState(NORTH_WALL, "none", "low", "tall") .enumState(SOUTH_WALL, "none", "low", "tall") .booleanState(UP) .booleanState(WATERLOGGED) .enumState(WEST_WALL, "none", "low", "tall"))); - public static final Block NETHER_BRICK_WALL = register(new Block("nether_brick_wall", builder() + public static final Block NETHER_BRICK_WALL = register(new Block("nether_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(EAST_WALL, "none", "low", "tall") .enumState(NORTH_WALL, "none", "low", "tall") .enumState(SOUTH_WALL, "none", "low", "tall") .booleanState(UP) .booleanState(WATERLOGGED) .enumState(WEST_WALL, "none", "low", "tall"))); - public static final Block ANDESITE_WALL = register(new Block("andesite_wall", builder() + public static final Block ANDESITE_WALL = register(new Block("andesite_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(EAST_WALL, "none", "low", "tall") .enumState(NORTH_WALL, "none", "low", "tall") .enumState(SOUTH_WALL, "none", "low", "tall") .booleanState(UP) .booleanState(WATERLOGGED) .enumState(WEST_WALL, "none", "low", "tall"))); - public static final Block RED_NETHER_BRICK_WALL = register(new Block("red_nether_brick_wall", builder() + public static final Block RED_NETHER_BRICK_WALL = register(new Block("red_nether_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(EAST_WALL, "none", "low", "tall") .enumState(NORTH_WALL, "none", "low", "tall") .enumState(SOUTH_WALL, "none", "low", "tall") .booleanState(UP) .booleanState(WATERLOGGED) .enumState(WEST_WALL, "none", "low", "tall"))); - public static final Block SANDSTONE_WALL = register(new Block("sandstone_wall", builder() + public static final Block SANDSTONE_WALL = register(new Block("sandstone_wall", builder().requiresCorrectToolForDrops().destroyTime(0.8f) .enumState(EAST_WALL, "none", "low", "tall") .enumState(NORTH_WALL, "none", "low", "tall") .enumState(SOUTH_WALL, "none", "low", "tall") .booleanState(UP) .booleanState(WATERLOGGED) .enumState(WEST_WALL, "none", "low", "tall"))); - public static final Block END_STONE_BRICK_WALL = register(new Block("end_stone_brick_wall", builder() + public static final Block END_STONE_BRICK_WALL = register(new Block("end_stone_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(EAST_WALL, "none", "low", "tall") .enumState(NORTH_WALL, "none", "low", "tall") .enumState(SOUTH_WALL, "none", "low", "tall") .booleanState(UP) .booleanState(WATERLOGGED) .enumState(WEST_WALL, "none", "low", "tall"))); - public static final Block DIORITE_WALL = register(new Block("diorite_wall", builder() + public static final Block DIORITE_WALL = register(new Block("diorite_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(EAST_WALL, "none", "low", "tall") .enumState(NORTH_WALL, "none", "low", "tall") .enumState(SOUTH_WALL, "none", "low", "tall") @@ -2001,75 +2001,75 @@ public final class Blocks { .booleanState(BOTTOM) .intState(STABILITY_DISTANCE, 0, 7) .booleanState(WATERLOGGED))); - public static final Block LOOM = register(new Block("loom", builder() + public static final Block LOOM = register(new Block("loom", builder().destroyTime(2.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block BARREL = register(new Block("barrel", builder() + public static final Block BARREL = register(new Block("barrel", builder().setBlockEntity().destroyTime(2.5f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .booleanState(OPEN))); - public static final Block SMOKER = register(new Block("smoker", builder() + public static final Block SMOKER = register(new Block("smoker", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(LIT))); - public static final Block BLAST_FURNACE = register(new Block("blast_furnace", builder() + public static final Block BLAST_FURNACE = register(new Block("blast_furnace", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(LIT))); - public static final Block CARTOGRAPHY_TABLE = register(new Block("cartography_table", builder())); - public static final Block FLETCHING_TABLE = register(new Block("fletching_table", builder())); - public static final Block GRINDSTONE = register(new Block("grindstone", builder() + public static final Block CARTOGRAPHY_TABLE = register(new Block("cartography_table", builder().destroyTime(2.5f))); + public static final Block FLETCHING_TABLE = register(new Block("fletching_table", builder().destroyTime(2.5f))); + public static final Block GRINDSTONE = register(new Block("grindstone", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block LECTERN = register(new Block("lectern", builder() + public static final Block LECTERN = register(new Block("lectern", builder().setBlockEntity().destroyTime(2.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(HAS_BOOK) .booleanState(POWERED))); - public static final Block SMITHING_TABLE = register(new Block("smithing_table", builder())); - public static final Block STONECUTTER = register(new Block("stonecutter", builder() + public static final Block SMITHING_TABLE = register(new Block("smithing_table", builder().destroyTime(2.5f))); + public static final Block STONECUTTER = register(new Block("stonecutter", builder().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block BELL = register(new Block("bell", builder() + public static final Block BELL = register(new Block("bell", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(5.0f) .enumState(BELL_ATTACHMENT, "floor", "ceiling", "single_wall", "double_wall") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block LANTERN = register(new Block("lantern", builder() + public static final Block LANTERN = register(new Block("lantern", builder().requiresCorrectToolForDrops().destroyTime(3.5f) .booleanState(HANGING) .booleanState(WATERLOGGED))); - public static final Block SOUL_LANTERN = register(new Block("soul_lantern", builder() + public static final Block SOUL_LANTERN = register(new Block("soul_lantern", builder().requiresCorrectToolForDrops().destroyTime(3.5f) .booleanState(HANGING) .booleanState(WATERLOGGED))); - public static final Block CAMPFIRE = register(new Block("campfire", builder() + public static final Block CAMPFIRE = register(new Block("campfire", builder().setBlockEntity().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(LIT) .booleanState(SIGNAL_FIRE) .booleanState(WATERLOGGED))); - public static final Block SOUL_CAMPFIRE = register(new Block("soul_campfire", builder() + public static final Block SOUL_CAMPFIRE = register(new Block("soul_campfire", builder().setBlockEntity().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(LIT) .booleanState(SIGNAL_FIRE) .booleanState(WATERLOGGED))); public static final Block SWEET_BERRY_BUSH = register(new Block("sweet_berry_bush", builder() .intState(AGE_3, 0, 3))); - public static final Block WARPED_STEM = register(new Block("warped_stem", builder() + public static final Block WARPED_STEM = register(new Block("warped_stem", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block STRIPPED_WARPED_STEM = register(new Block("stripped_warped_stem", builder() + public static final Block STRIPPED_WARPED_STEM = register(new Block("stripped_warped_stem", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block WARPED_HYPHAE = register(new Block("warped_hyphae", builder() + public static final Block WARPED_HYPHAE = register(new Block("warped_hyphae", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block STRIPPED_WARPED_HYPHAE = register(new Block("stripped_warped_hyphae", builder() + public static final Block STRIPPED_WARPED_HYPHAE = register(new Block("stripped_warped_hyphae", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block WARPED_NYLIUM = register(new Block("warped_nylium", builder())); + public static final Block WARPED_NYLIUM = register(new Block("warped_nylium", builder().requiresCorrectToolForDrops().destroyTime(0.4f))); public static final Block WARPED_FUNGUS = register(new Block("warped_fungus", builder())); - public static final Block WARPED_WART_BLOCK = register(new Block("warped_wart_block", builder())); + public static final Block WARPED_WART_BLOCK = register(new Block("warped_wart_block", builder().destroyTime(1.0f))); public static final Block WARPED_ROOTS = register(new Block("warped_roots", builder())); public static final Block NETHER_SPROUTS = register(new Block("nether_sprouts", builder())); - public static final Block CRIMSON_STEM = register(new Block("crimson_stem", builder() + public static final Block CRIMSON_STEM = register(new Block("crimson_stem", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block STRIPPED_CRIMSON_STEM = register(new Block("stripped_crimson_stem", builder() + public static final Block STRIPPED_CRIMSON_STEM = register(new Block("stripped_crimson_stem", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block CRIMSON_HYPHAE = register(new Block("crimson_hyphae", builder() + public static final Block CRIMSON_HYPHAE = register(new Block("crimson_hyphae", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block STRIPPED_CRIMSON_HYPHAE = register(new Block("stripped_crimson_hyphae", builder() + public static final Block STRIPPED_CRIMSON_HYPHAE = register(new Block("stripped_crimson_hyphae", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block CRIMSON_NYLIUM = register(new Block("crimson_nylium", builder())); + public static final Block CRIMSON_NYLIUM = register(new Block("crimson_nylium", builder().requiresCorrectToolForDrops().destroyTime(0.4f))); public static final Block CRIMSON_FUNGUS = register(new Block("crimson_fungus", builder())); - public static final Block SHROOMLIGHT = register(new Block("shroomlight", builder())); + public static final Block SHROOMLIGHT = register(new Block("shroomlight", builder().destroyTime(1.0f))); public static final Block WEEPING_VINES = register(new Block("weeping_vines", builder() .intState(AGE_25, 0, 25))); public static final Block WEEPING_VINES_PLANT = register(new Block("weeping_vines_plant", builder())); @@ -2077,360 +2077,360 @@ public final class Blocks { .intState(AGE_25, 0, 25))); public static final Block TWISTING_VINES_PLANT = register(new Block("twisting_vines_plant", builder())); public static final Block CRIMSON_ROOTS = register(new Block("crimson_roots", builder())); - public static final Block CRIMSON_PLANKS = register(new Block("crimson_planks", builder())); - public static final Block WARPED_PLANKS = register(new Block("warped_planks", builder())); - public static final Block CRIMSON_SLAB = register(new Block("crimson_slab", builder() + public static final Block CRIMSON_PLANKS = register(new Block("crimson_planks", builder().destroyTime(2.0f))); + public static final Block WARPED_PLANKS = register(new Block("warped_planks", builder().destroyTime(2.0f))); + public static final Block CRIMSON_SLAB = register(new Block("crimson_slab", builder().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block WARPED_SLAB = register(new Block("warped_slab", builder() + public static final Block WARPED_SLAB = register(new Block("warped_slab", builder().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block CRIMSON_PRESSURE_PLATE = register(new Block("crimson_pressure_plate", builder() + public static final Block CRIMSON_PRESSURE_PLATE = register(new Block("crimson_pressure_plate", builder().destroyTime(0.5f) .booleanState(POWERED))); - public static final Block WARPED_PRESSURE_PLATE = register(new Block("warped_pressure_plate", builder() + public static final Block WARPED_PRESSURE_PLATE = register(new Block("warped_pressure_plate", builder().destroyTime(0.5f) .booleanState(POWERED))); - public static final Block CRIMSON_FENCE = register(new Block("crimson_fence", builder() + public static final Block CRIMSON_FENCE = register(new Block("crimson_fence", builder().destroyTime(2.0f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block WARPED_FENCE = register(new Block("warped_fence", builder() + public static final Block WARPED_FENCE = register(new Block("warped_fence", builder().destroyTime(2.0f) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block CRIMSON_TRAPDOOR = register(new Block("crimson_trapdoor", builder() + public static final Block CRIMSON_TRAPDOOR = register(new Block("crimson_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block WARPED_TRAPDOOR = register(new Block("warped_trapdoor", builder() + public static final Block WARPED_TRAPDOOR = register(new Block("warped_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block CRIMSON_FENCE_GATE = register(new Block("crimson_fence_gate", builder() + public static final Block CRIMSON_FENCE_GATE = register(new Block("crimson_fence_gate", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(IN_WALL) .booleanState(OPEN) .booleanState(POWERED))); - public static final Block WARPED_FENCE_GATE = register(new Block("warped_fence_gate", builder() + public static final Block WARPED_FENCE_GATE = register(new Block("warped_fence_gate", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(IN_WALL) .booleanState(OPEN) .booleanState(POWERED))); - public static final Block CRIMSON_STAIRS = register(new Block("crimson_stairs", builder() + public static final Block CRIMSON_STAIRS = register(new Block("crimson_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block WARPED_STAIRS = register(new Block("warped_stairs", builder() + public static final Block WARPED_STAIRS = register(new Block("warped_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block CRIMSON_BUTTON = register(new Block("crimson_button", builder() + public static final Block CRIMSON_BUTTON = register(new Block("crimson_button", builder().destroyTime(0.5f) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block WARPED_BUTTON = register(new Block("warped_button", builder() + public static final Block WARPED_BUTTON = register(new Block("warped_button", builder().destroyTime(0.5f) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block CRIMSON_DOOR = register(new Block("crimson_door", builder() + public static final Block CRIMSON_DOOR = register(new Block("crimson_door", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block WARPED_DOOR = register(new Block("warped_door", builder() + public static final Block WARPED_DOOR = register(new Block("warped_door", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block CRIMSON_SIGN = register(new Block("crimson_sign", builder() + public static final Block CRIMSON_SIGN = register(new Block("crimson_sign", builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15) .booleanState(WATERLOGGED))); - public static final Block WARPED_SIGN = register(new Block("warped_sign", builder() + public static final Block WARPED_SIGN = register(new Block("warped_sign", builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15) .booleanState(WATERLOGGED))); - public static final Block CRIMSON_WALL_SIGN = register(new Block("crimson_wall_sign", builder() + public static final Block CRIMSON_WALL_SIGN = register(new Block("crimson_wall_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block WARPED_WALL_SIGN = register(new Block("warped_wall_sign", builder() + public static final Block WARPED_WALL_SIGN = register(new Block("warped_wall_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block STRUCTURE_BLOCK = register(new Block("structure_block", builder() + public static final Block STRUCTURE_BLOCK = register(new Block("structure_block", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(-1.0f) .enumState(STRUCTUREBLOCK_MODE, "save", "load", "corner", "data"))); - public static final Block JIGSAW = register(new Block("jigsaw", builder() + public static final Block JIGSAW = register(new Block("jigsaw", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(-1.0f) .enumState(ORIENTATION, "down_east", "down_north", "down_south", "down_west", "up_east", "up_north", "up_south", "up_west", "west_up", "east_up", "north_up", "south_up"))); - public static final Block COMPOSTER = register(new Block("composter", builder() + public static final Block COMPOSTER = register(new Block("composter", builder().destroyTime(0.6f) .intState(LEVEL_COMPOSTER, 0, 8))); - public static final Block TARGET = register(new Block("target", builder() + public static final Block TARGET = register(new Block("target", builder().destroyTime(0.5f) .intState(POWER, 0, 15))); - public static final Block BEE_NEST = register(new Block("bee_nest", builder() + public static final Block BEE_NEST = register(new Block("bee_nest", builder().setBlockEntity().destroyTime(0.3f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .intState(LEVEL_HONEY, 0, 5))); - public static final Block BEEHIVE = register(new Block("beehive", builder() + public static final Block BEEHIVE = register(new Block("beehive", builder().setBlockEntity().destroyTime(0.6f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .intState(LEVEL_HONEY, 0, 5))); public static final Block HONEY_BLOCK = register(new Block("honey_block", builder())); - public static final Block HONEYCOMB_BLOCK = register(new Block("honeycomb_block", builder())); - public static final Block NETHERITE_BLOCK = register(new Block("netherite_block", builder())); - public static final Block ANCIENT_DEBRIS = register(new Block("ancient_debris", builder())); - public static final Block CRYING_OBSIDIAN = register(new Block("crying_obsidian", builder())); - public static final Block RESPAWN_ANCHOR = register(new Block("respawn_anchor", builder() + public static final Block HONEYCOMB_BLOCK = register(new Block("honeycomb_block", builder().destroyTime(0.6f))); + public static final Block NETHERITE_BLOCK = register(new Block("netherite_block", builder().requiresCorrectToolForDrops().destroyTime(50.0f))); + public static final Block ANCIENT_DEBRIS = register(new Block("ancient_debris", builder().requiresCorrectToolForDrops().destroyTime(30.0f))); + public static final Block CRYING_OBSIDIAN = register(new Block("crying_obsidian", builder().requiresCorrectToolForDrops().destroyTime(50.0f))); + public static final Block RESPAWN_ANCHOR = register(new Block("respawn_anchor", builder().requiresCorrectToolForDrops().destroyTime(50.0f) .intState(RESPAWN_ANCHOR_CHARGES, 0, 4))); public static final Block POTTED_CRIMSON_FUNGUS = register(new Block("potted_crimson_fungus", builder())); public static final Block POTTED_WARPED_FUNGUS = register(new Block("potted_warped_fungus", builder())); public static final Block POTTED_CRIMSON_ROOTS = register(new Block("potted_crimson_roots", builder())); public static final Block POTTED_WARPED_ROOTS = register(new Block("potted_warped_roots", builder())); - public static final Block LODESTONE = register(new Block("lodestone", builder())); - public static final Block BLACKSTONE = register(new Block("blackstone", builder())); - public static final Block BLACKSTONE_STAIRS = register(new Block("blackstone_stairs", builder() + public static final Block LODESTONE = register(new Block("lodestone", builder().requiresCorrectToolForDrops().destroyTime(3.5f))); + public static final Block BLACKSTONE = register(new Block("blackstone", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block BLACKSTONE_STAIRS = register(new Block("blackstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block BLACKSTONE_WALL = register(new Block("blackstone_wall", builder() + public static final Block BLACKSTONE_WALL = register(new Block("blackstone_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(EAST_WALL, "none", "low", "tall") .enumState(NORTH_WALL, "none", "low", "tall") .enumState(SOUTH_WALL, "none", "low", "tall") .booleanState(UP) .booleanState(WATERLOGGED) .enumState(WEST_WALL, "none", "low", "tall"))); - public static final Block BLACKSTONE_SLAB = register(new Block("blackstone_slab", builder() + public static final Block BLACKSTONE_SLAB = register(new Block("blackstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block POLISHED_BLACKSTONE = register(new Block("polished_blackstone", builder())); - public static final Block POLISHED_BLACKSTONE_BRICKS = register(new Block("polished_blackstone_bricks", builder())); - public static final Block CRACKED_POLISHED_BLACKSTONE_BRICKS = register(new Block("cracked_polished_blackstone_bricks", builder())); - public static final Block CHISELED_POLISHED_BLACKSTONE = register(new Block("chiseled_polished_blackstone", builder())); - public static final Block POLISHED_BLACKSTONE_BRICK_SLAB = register(new Block("polished_blackstone_brick_slab", builder() + public static final Block POLISHED_BLACKSTONE = register(new Block("polished_blackstone", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); + public static final Block POLISHED_BLACKSTONE_BRICKS = register(new Block("polished_blackstone_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block CRACKED_POLISHED_BLACKSTONE_BRICKS = register(new Block("cracked_polished_blackstone_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block CHISELED_POLISHED_BLACKSTONE = register(new Block("chiseled_polished_blackstone", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block POLISHED_BLACKSTONE_BRICK_SLAB = register(new Block("polished_blackstone_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block POLISHED_BLACKSTONE_BRICK_STAIRS = register(new Block("polished_blackstone_brick_stairs", builder() + public static final Block POLISHED_BLACKSTONE_BRICK_STAIRS = register(new Block("polished_blackstone_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block POLISHED_BLACKSTONE_BRICK_WALL = register(new Block("polished_blackstone_brick_wall", builder() + public static final Block POLISHED_BLACKSTONE_BRICK_WALL = register(new Block("polished_blackstone_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(EAST_WALL, "none", "low", "tall") .enumState(NORTH_WALL, "none", "low", "tall") .enumState(SOUTH_WALL, "none", "low", "tall") .booleanState(UP) .booleanState(WATERLOGGED) .enumState(WEST_WALL, "none", "low", "tall"))); - public static final Block GILDED_BLACKSTONE = register(new Block("gilded_blackstone", builder())); - public static final Block POLISHED_BLACKSTONE_STAIRS = register(new Block("polished_blackstone_stairs", builder() + public static final Block GILDED_BLACKSTONE = register(new Block("gilded_blackstone", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block POLISHED_BLACKSTONE_STAIRS = register(new Block("polished_blackstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block POLISHED_BLACKSTONE_SLAB = register(new Block("polished_blackstone_slab", builder() + public static final Block POLISHED_BLACKSTONE_SLAB = register(new Block("polished_blackstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block POLISHED_BLACKSTONE_PRESSURE_PLATE = register(new Block("polished_blackstone_pressure_plate", builder() + public static final Block POLISHED_BLACKSTONE_PRESSURE_PLATE = register(new Block("polished_blackstone_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f) .booleanState(POWERED))); - public static final Block POLISHED_BLACKSTONE_BUTTON = register(new Block("polished_blackstone_button", builder() + public static final Block POLISHED_BLACKSTONE_BUTTON = register(new Block("polished_blackstone_button", builder().destroyTime(0.5f) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block POLISHED_BLACKSTONE_WALL = register(new Block("polished_blackstone_wall", builder() + public static final Block POLISHED_BLACKSTONE_WALL = register(new Block("polished_blackstone_wall", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(EAST_WALL, "none", "low", "tall") .enumState(NORTH_WALL, "none", "low", "tall") .enumState(SOUTH_WALL, "none", "low", "tall") .booleanState(UP) .booleanState(WATERLOGGED) .enumState(WEST_WALL, "none", "low", "tall"))); - public static final Block CHISELED_NETHER_BRICKS = register(new Block("chiseled_nether_bricks", builder())); - public static final Block CRACKED_NETHER_BRICKS = register(new Block("cracked_nether_bricks", builder())); - public static final Block QUARTZ_BRICKS = register(new Block("quartz_bricks", builder())); - public static final Block CANDLE = register(new Block("candle", builder() + public static final Block CHISELED_NETHER_BRICKS = register(new Block("chiseled_nether_bricks", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); + public static final Block CRACKED_NETHER_BRICKS = register(new Block("cracked_nether_bricks", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); + public static final Block QUARTZ_BRICKS = register(new Block("quartz_bricks", builder().requiresCorrectToolForDrops().destroyTime(0.8f))); + public static final Block CANDLE = register(new Block("candle", builder().destroyTime(0.1f) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block WHITE_CANDLE = register(new Block("white_candle", builder() + public static final Block WHITE_CANDLE = register(new Block("white_candle", builder().destroyTime(0.1f) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block ORANGE_CANDLE = register(new Block("orange_candle", builder() + public static final Block ORANGE_CANDLE = register(new Block("orange_candle", builder().destroyTime(0.1f) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block MAGENTA_CANDLE = register(new Block("magenta_candle", builder() + public static final Block MAGENTA_CANDLE = register(new Block("magenta_candle", builder().destroyTime(0.1f) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block LIGHT_BLUE_CANDLE = register(new Block("light_blue_candle", builder() + public static final Block LIGHT_BLUE_CANDLE = register(new Block("light_blue_candle", builder().destroyTime(0.1f) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block YELLOW_CANDLE = register(new Block("yellow_candle", builder() + public static final Block YELLOW_CANDLE = register(new Block("yellow_candle", builder().destroyTime(0.1f) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block LIME_CANDLE = register(new Block("lime_candle", builder() + public static final Block LIME_CANDLE = register(new Block("lime_candle", builder().destroyTime(0.1f) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block PINK_CANDLE = register(new Block("pink_candle", builder() + public static final Block PINK_CANDLE = register(new Block("pink_candle", builder().destroyTime(0.1f) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block GRAY_CANDLE = register(new Block("gray_candle", builder() + public static final Block GRAY_CANDLE = register(new Block("gray_candle", builder().destroyTime(0.1f) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block LIGHT_GRAY_CANDLE = register(new Block("light_gray_candle", builder() + public static final Block LIGHT_GRAY_CANDLE = register(new Block("light_gray_candle", builder().destroyTime(0.1f) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block CYAN_CANDLE = register(new Block("cyan_candle", builder() + public static final Block CYAN_CANDLE = register(new Block("cyan_candle", builder().destroyTime(0.1f) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block PURPLE_CANDLE = register(new Block("purple_candle", builder() + public static final Block PURPLE_CANDLE = register(new Block("purple_candle", builder().destroyTime(0.1f) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block BLUE_CANDLE = register(new Block("blue_candle", builder() + public static final Block BLUE_CANDLE = register(new Block("blue_candle", builder().destroyTime(0.1f) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block BROWN_CANDLE = register(new Block("brown_candle", builder() + public static final Block BROWN_CANDLE = register(new Block("brown_candle", builder().destroyTime(0.1f) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block GREEN_CANDLE = register(new Block("green_candle", builder() + public static final Block GREEN_CANDLE = register(new Block("green_candle", builder().destroyTime(0.1f) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block RED_CANDLE = register(new Block("red_candle", builder() + public static final Block RED_CANDLE = register(new Block("red_candle", builder().destroyTime(0.1f) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block BLACK_CANDLE = register(new Block("black_candle", builder() + public static final Block BLACK_CANDLE = register(new Block("black_candle", builder().destroyTime(0.1f) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block CANDLE_CAKE = register(new Block("candle_cake", builder() + public static final Block CANDLE_CAKE = register(new Block("candle_cake", builder().destroyTime(0.5f) .booleanState(LIT))); - public static final Block WHITE_CANDLE_CAKE = register(new Block("white_candle_cake", builder() + public static final Block WHITE_CANDLE_CAKE = register(new Block("white_candle_cake", builder().destroyTime(0.5f) .booleanState(LIT))); - public static final Block ORANGE_CANDLE_CAKE = register(new Block("orange_candle_cake", builder() + public static final Block ORANGE_CANDLE_CAKE = register(new Block("orange_candle_cake", builder().destroyTime(0.5f) .booleanState(LIT))); - public static final Block MAGENTA_CANDLE_CAKE = register(new Block("magenta_candle_cake", builder() + public static final Block MAGENTA_CANDLE_CAKE = register(new Block("magenta_candle_cake", builder().destroyTime(0.5f) .booleanState(LIT))); - public static final Block LIGHT_BLUE_CANDLE_CAKE = register(new Block("light_blue_candle_cake", builder() + public static final Block LIGHT_BLUE_CANDLE_CAKE = register(new Block("light_blue_candle_cake", builder().destroyTime(0.5f) .booleanState(LIT))); - public static final Block YELLOW_CANDLE_CAKE = register(new Block("yellow_candle_cake", builder() + public static final Block YELLOW_CANDLE_CAKE = register(new Block("yellow_candle_cake", builder().destroyTime(0.5f) .booleanState(LIT))); - public static final Block LIME_CANDLE_CAKE = register(new Block("lime_candle_cake", builder() + public static final Block LIME_CANDLE_CAKE = register(new Block("lime_candle_cake", builder().destroyTime(0.5f) .booleanState(LIT))); - public static final Block PINK_CANDLE_CAKE = register(new Block("pink_candle_cake", builder() + public static final Block PINK_CANDLE_CAKE = register(new Block("pink_candle_cake", builder().destroyTime(0.5f) .booleanState(LIT))); - public static final Block GRAY_CANDLE_CAKE = register(new Block("gray_candle_cake", builder() + public static final Block GRAY_CANDLE_CAKE = register(new Block("gray_candle_cake", builder().destroyTime(0.5f) .booleanState(LIT))); - public static final Block LIGHT_GRAY_CANDLE_CAKE = register(new Block("light_gray_candle_cake", builder() + public static final Block LIGHT_GRAY_CANDLE_CAKE = register(new Block("light_gray_candle_cake", builder().destroyTime(0.5f) .booleanState(LIT))); - public static final Block CYAN_CANDLE_CAKE = register(new Block("cyan_candle_cake", builder() + public static final Block CYAN_CANDLE_CAKE = register(new Block("cyan_candle_cake", builder().destroyTime(0.5f) .booleanState(LIT))); - public static final Block PURPLE_CANDLE_CAKE = register(new Block("purple_candle_cake", builder() + public static final Block PURPLE_CANDLE_CAKE = register(new Block("purple_candle_cake", builder().destroyTime(0.5f) .booleanState(LIT))); - public static final Block BLUE_CANDLE_CAKE = register(new Block("blue_candle_cake", builder() + public static final Block BLUE_CANDLE_CAKE = register(new Block("blue_candle_cake", builder().destroyTime(0.5f) .booleanState(LIT))); - public static final Block BROWN_CANDLE_CAKE = register(new Block("brown_candle_cake", builder() + public static final Block BROWN_CANDLE_CAKE = register(new Block("brown_candle_cake", builder().destroyTime(0.5f) .booleanState(LIT))); - public static final Block GREEN_CANDLE_CAKE = register(new Block("green_candle_cake", builder() + public static final Block GREEN_CANDLE_CAKE = register(new Block("green_candle_cake", builder().destroyTime(0.5f) .booleanState(LIT))); - public static final Block RED_CANDLE_CAKE = register(new Block("red_candle_cake", builder() + public static final Block RED_CANDLE_CAKE = register(new Block("red_candle_cake", builder().destroyTime(0.5f) .booleanState(LIT))); - public static final Block BLACK_CANDLE_CAKE = register(new Block("black_candle_cake", builder() + public static final Block BLACK_CANDLE_CAKE = register(new Block("black_candle_cake", builder().destroyTime(0.5f) .booleanState(LIT))); - public static final Block AMETHYST_BLOCK = register(new Block("amethyst_block", builder())); - public static final Block BUDDING_AMETHYST = register(new Block("budding_amethyst", builder())); - public static final Block AMETHYST_CLUSTER = register(new Block("amethyst_cluster", builder() + public static final Block AMETHYST_BLOCK = register(new Block("amethyst_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block BUDDING_AMETHYST = register(new Block("budding_amethyst", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block AMETHYST_CLUSTER = register(new Block("amethyst_cluster", builder().destroyTime(1.5f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .booleanState(WATERLOGGED))); - public static final Block LARGE_AMETHYST_BUD = register(new Block("large_amethyst_bud", builder() + public static final Block LARGE_AMETHYST_BUD = register(new Block("large_amethyst_bud", builder().destroyTime(1.5f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .booleanState(WATERLOGGED))); - public static final Block MEDIUM_AMETHYST_BUD = register(new Block("medium_amethyst_bud", builder() + public static final Block MEDIUM_AMETHYST_BUD = register(new Block("medium_amethyst_bud", builder().destroyTime(1.5f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .booleanState(WATERLOGGED))); - public static final Block SMALL_AMETHYST_BUD = register(new Block("small_amethyst_bud", builder() + public static final Block SMALL_AMETHYST_BUD = register(new Block("small_amethyst_bud", builder().destroyTime(1.5f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .booleanState(WATERLOGGED))); - public static final Block TUFF = register(new Block("tuff", builder())); - public static final Block TUFF_SLAB = register(new Block("tuff_slab", builder() + public static final Block TUFF = register(new Block("tuff", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block TUFF_SLAB = register(new Block("tuff_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block TUFF_STAIRS = register(new Block("tuff_stairs", builder() + public static final Block TUFF_STAIRS = register(new Block("tuff_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block TUFF_WALL = register(new Block("tuff_wall", builder() + public static final Block TUFF_WALL = register(new Block("tuff_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(EAST_WALL, "none", "low", "tall") .enumState(NORTH_WALL, "none", "low", "tall") .enumState(SOUTH_WALL, "none", "low", "tall") .booleanState(UP) .booleanState(WATERLOGGED) .enumState(WEST_WALL, "none", "low", "tall"))); - public static final Block POLISHED_TUFF = register(new Block("polished_tuff", builder())); - public static final Block POLISHED_TUFF_SLAB = register(new Block("polished_tuff_slab", builder() + public static final Block POLISHED_TUFF = register(new Block("polished_tuff", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block POLISHED_TUFF_SLAB = register(new Block("polished_tuff_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block POLISHED_TUFF_STAIRS = register(new Block("polished_tuff_stairs", builder() + public static final Block POLISHED_TUFF_STAIRS = register(new Block("polished_tuff_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block POLISHED_TUFF_WALL = register(new Block("polished_tuff_wall", builder() + public static final Block POLISHED_TUFF_WALL = register(new Block("polished_tuff_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(EAST_WALL, "none", "low", "tall") .enumState(NORTH_WALL, "none", "low", "tall") .enumState(SOUTH_WALL, "none", "low", "tall") .booleanState(UP) .booleanState(WATERLOGGED) .enumState(WEST_WALL, "none", "low", "tall"))); - public static final Block CHISELED_TUFF = register(new Block("chiseled_tuff", builder())); - public static final Block TUFF_BRICKS = register(new Block("tuff_bricks", builder())); - public static final Block TUFF_BRICK_SLAB = register(new Block("tuff_brick_slab", builder() + public static final Block CHISELED_TUFF = register(new Block("chiseled_tuff", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block TUFF_BRICKS = register(new Block("tuff_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block TUFF_BRICK_SLAB = register(new Block("tuff_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block TUFF_BRICK_STAIRS = register(new Block("tuff_brick_stairs", builder() + public static final Block TUFF_BRICK_STAIRS = register(new Block("tuff_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block TUFF_BRICK_WALL = register(new Block("tuff_brick_wall", builder() + public static final Block TUFF_BRICK_WALL = register(new Block("tuff_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(EAST_WALL, "none", "low", "tall") .enumState(NORTH_WALL, "none", "low", "tall") .enumState(SOUTH_WALL, "none", "low", "tall") .booleanState(UP) .booleanState(WATERLOGGED) .enumState(WEST_WALL, "none", "low", "tall"))); - public static final Block CHISELED_TUFF_BRICKS = register(new Block("chiseled_tuff_bricks", builder())); - public static final Block CALCITE = register(new Block("calcite", builder())); - public static final Block TINTED_GLASS = register(new Block("tinted_glass", builder())); - public static final Block POWDER_SNOW = register(new Block("powder_snow", builder())); - public static final Block SCULK_SENSOR = register(new Block("sculk_sensor", builder() + public static final Block CHISELED_TUFF_BRICKS = register(new Block("chiseled_tuff_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); + public static final Block CALCITE = register(new Block("calcite", builder().requiresCorrectToolForDrops().destroyTime(0.75f))); + public static final Block TINTED_GLASS = register(new Block("tinted_glass", builder().destroyTime(0.3f))); + public static final Block POWDER_SNOW = register(new Block("powder_snow", builder().destroyTime(0.25f))); + public static final Block SCULK_SENSOR = register(new Block("sculk_sensor", builder().setBlockEntity().destroyTime(1.5f) .intState(POWER, 0, 15) .enumState(SCULK_SENSOR_PHASE, "inactive", "active", "cooldown") .booleanState(WATERLOGGED))); - public static final Block CALIBRATED_SCULK_SENSOR = register(new Block("calibrated_sculk_sensor", builder() + public static final Block CALIBRATED_SCULK_SENSOR = register(new Block("calibrated_sculk_sensor", builder().setBlockEntity().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .intState(POWER, 0, 15) .enumState(SCULK_SENSOR_PHASE, "inactive", "active", "cooldown") .booleanState(WATERLOGGED))); - public static final Block SCULK = register(new Block("sculk", builder())); - public static final Block SCULK_VEIN = register(new Block("sculk_vein", builder() + public static final Block SCULK = register(new Block("sculk", builder().destroyTime(0.2f))); + public static final Block SCULK_VEIN = register(new Block("sculk_vein", builder().destroyTime(0.2f) .booleanState(DOWN) .booleanState(EAST) .booleanState(NORTH) @@ -2438,247 +2438,247 @@ public final class Blocks { .booleanState(UP) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block SCULK_CATALYST = register(new Block("sculk_catalyst", builder() + public static final Block SCULK_CATALYST = register(new Block("sculk_catalyst", builder().setBlockEntity().destroyTime(3.0f) .booleanState(BLOOM))); - public static final Block SCULK_SHRIEKER = register(new Block("sculk_shrieker", builder() + public static final Block SCULK_SHRIEKER = register(new Block("sculk_shrieker", builder().setBlockEntity().destroyTime(3.0f) .booleanState(CAN_SUMMON) .booleanState(SHRIEKING) .booleanState(WATERLOGGED))); - public static final Block COPPER_BLOCK = register(new Block("copper_block", builder())); - public static final Block EXPOSED_COPPER = register(new Block("exposed_copper", builder())); - public static final Block WEATHERED_COPPER = register(new Block("weathered_copper", builder())); - public static final Block OXIDIZED_COPPER = register(new Block("oxidized_copper", builder())); - public static final Block COPPER_ORE = register(new Block("copper_ore", builder())); - public static final Block DEEPSLATE_COPPER_ORE = register(new Block("deepslate_copper_ore", builder())); - public static final Block OXIDIZED_CUT_COPPER = register(new Block("oxidized_cut_copper", builder())); - public static final Block WEATHERED_CUT_COPPER = register(new Block("weathered_cut_copper", builder())); - public static final Block EXPOSED_CUT_COPPER = register(new Block("exposed_cut_copper", builder())); - public static final Block CUT_COPPER = register(new Block("cut_copper", builder())); - public static final Block OXIDIZED_CHISELED_COPPER = register(new Block("oxidized_chiseled_copper", builder())); - public static final Block WEATHERED_CHISELED_COPPER = register(new Block("weathered_chiseled_copper", builder())); - public static final Block EXPOSED_CHISELED_COPPER = register(new Block("exposed_chiseled_copper", builder())); - public static final Block CHISELED_COPPER = register(new Block("chiseled_copper", builder())); - public static final Block WAXED_OXIDIZED_CHISELED_COPPER = register(new Block("waxed_oxidized_chiseled_copper", builder())); - public static final Block WAXED_WEATHERED_CHISELED_COPPER = register(new Block("waxed_weathered_chiseled_copper", builder())); - public static final Block WAXED_EXPOSED_CHISELED_COPPER = register(new Block("waxed_exposed_chiseled_copper", builder())); - public static final Block WAXED_CHISELED_COPPER = register(new Block("waxed_chiseled_copper", builder())); - public static final Block OXIDIZED_CUT_COPPER_STAIRS = register(new Block("oxidized_cut_copper_stairs", builder() + public static final Block COPPER_BLOCK = register(new Block("copper_block", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block EXPOSED_COPPER = register(new Block("exposed_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block WEATHERED_COPPER = register(new Block("weathered_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block OXIDIZED_COPPER = register(new Block("oxidized_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block COPPER_ORE = register(new Block("copper_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block DEEPSLATE_COPPER_ORE = register(new Block("deepslate_copper_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f))); + public static final Block OXIDIZED_CUT_COPPER = register(new Block("oxidized_cut_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block WEATHERED_CUT_COPPER = register(new Block("weathered_cut_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block EXPOSED_CUT_COPPER = register(new Block("exposed_cut_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block CUT_COPPER = register(new Block("cut_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block OXIDIZED_CHISELED_COPPER = register(new Block("oxidized_chiseled_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block WEATHERED_CHISELED_COPPER = register(new Block("weathered_chiseled_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block EXPOSED_CHISELED_COPPER = register(new Block("exposed_chiseled_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block CHISELED_COPPER = register(new Block("chiseled_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block WAXED_OXIDIZED_CHISELED_COPPER = register(new Block("waxed_oxidized_chiseled_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block WAXED_WEATHERED_CHISELED_COPPER = register(new Block("waxed_weathered_chiseled_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block WAXED_EXPOSED_CHISELED_COPPER = register(new Block("waxed_exposed_chiseled_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block WAXED_CHISELED_COPPER = register(new Block("waxed_chiseled_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block OXIDIZED_CUT_COPPER_STAIRS = register(new Block("oxidized_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block WEATHERED_CUT_COPPER_STAIRS = register(new Block("weathered_cut_copper_stairs", builder() + public static final Block WEATHERED_CUT_COPPER_STAIRS = register(new Block("weathered_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block EXPOSED_CUT_COPPER_STAIRS = register(new Block("exposed_cut_copper_stairs", builder() + public static final Block EXPOSED_CUT_COPPER_STAIRS = register(new Block("exposed_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block CUT_COPPER_STAIRS = register(new Block("cut_copper_stairs", builder() + public static final Block CUT_COPPER_STAIRS = register(new Block("cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block OXIDIZED_CUT_COPPER_SLAB = register(new Block("oxidized_cut_copper_slab", builder() + public static final Block OXIDIZED_CUT_COPPER_SLAB = register(new Block("oxidized_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block WEATHERED_CUT_COPPER_SLAB = register(new Block("weathered_cut_copper_slab", builder() + public static final Block WEATHERED_CUT_COPPER_SLAB = register(new Block("weathered_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block EXPOSED_CUT_COPPER_SLAB = register(new Block("exposed_cut_copper_slab", builder() + public static final Block EXPOSED_CUT_COPPER_SLAB = register(new Block("exposed_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block CUT_COPPER_SLAB = register(new Block("cut_copper_slab", builder() + public static final Block CUT_COPPER_SLAB = register(new Block("cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block WAXED_COPPER_BLOCK = register(new Block("waxed_copper_block", builder())); - public static final Block WAXED_WEATHERED_COPPER = register(new Block("waxed_weathered_copper", builder())); - public static final Block WAXED_EXPOSED_COPPER = register(new Block("waxed_exposed_copper", builder())); - public static final Block WAXED_OXIDIZED_COPPER = register(new Block("waxed_oxidized_copper", builder())); - public static final Block WAXED_OXIDIZED_CUT_COPPER = register(new Block("waxed_oxidized_cut_copper", builder())); - public static final Block WAXED_WEATHERED_CUT_COPPER = register(new Block("waxed_weathered_cut_copper", builder())); - public static final Block WAXED_EXPOSED_CUT_COPPER = register(new Block("waxed_exposed_cut_copper", builder())); - public static final Block WAXED_CUT_COPPER = register(new Block("waxed_cut_copper", builder())); - public static final Block WAXED_OXIDIZED_CUT_COPPER_STAIRS = register(new Block("waxed_oxidized_cut_copper_stairs", builder() + public static final Block WAXED_COPPER_BLOCK = register(new Block("waxed_copper_block", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block WAXED_WEATHERED_COPPER = register(new Block("waxed_weathered_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block WAXED_EXPOSED_COPPER = register(new Block("waxed_exposed_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block WAXED_OXIDIZED_COPPER = register(new Block("waxed_oxidized_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block WAXED_OXIDIZED_CUT_COPPER = register(new Block("waxed_oxidized_cut_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block WAXED_WEATHERED_CUT_COPPER = register(new Block("waxed_weathered_cut_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block WAXED_EXPOSED_CUT_COPPER = register(new Block("waxed_exposed_cut_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block WAXED_CUT_COPPER = register(new Block("waxed_cut_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); + public static final Block WAXED_OXIDIZED_CUT_COPPER_STAIRS = register(new Block("waxed_oxidized_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block WAXED_WEATHERED_CUT_COPPER_STAIRS = register(new Block("waxed_weathered_cut_copper_stairs", builder() + public static final Block WAXED_WEATHERED_CUT_COPPER_STAIRS = register(new Block("waxed_weathered_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block WAXED_EXPOSED_CUT_COPPER_STAIRS = register(new Block("waxed_exposed_cut_copper_stairs", builder() + public static final Block WAXED_EXPOSED_CUT_COPPER_STAIRS = register(new Block("waxed_exposed_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block WAXED_CUT_COPPER_STAIRS = register(new Block("waxed_cut_copper_stairs", builder() + public static final Block WAXED_CUT_COPPER_STAIRS = register(new Block("waxed_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block WAXED_OXIDIZED_CUT_COPPER_SLAB = register(new Block("waxed_oxidized_cut_copper_slab", builder() + public static final Block WAXED_OXIDIZED_CUT_COPPER_SLAB = register(new Block("waxed_oxidized_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block WAXED_WEATHERED_CUT_COPPER_SLAB = register(new Block("waxed_weathered_cut_copper_slab", builder() + public static final Block WAXED_WEATHERED_CUT_COPPER_SLAB = register(new Block("waxed_weathered_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block WAXED_EXPOSED_CUT_COPPER_SLAB = register(new Block("waxed_exposed_cut_copper_slab", builder() + public static final Block WAXED_EXPOSED_CUT_COPPER_SLAB = register(new Block("waxed_exposed_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block WAXED_CUT_COPPER_SLAB = register(new Block("waxed_cut_copper_slab", builder() + public static final Block WAXED_CUT_COPPER_SLAB = register(new Block("waxed_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block COPPER_DOOR = register(new Block("copper_door", builder() + public static final Block COPPER_DOOR = register(new Block("copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block EXPOSED_COPPER_DOOR = register(new Block("exposed_copper_door", builder() + public static final Block EXPOSED_COPPER_DOOR = register(new Block("exposed_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block OXIDIZED_COPPER_DOOR = register(new Block("oxidized_copper_door", builder() + public static final Block OXIDIZED_COPPER_DOOR = register(new Block("oxidized_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block WEATHERED_COPPER_DOOR = register(new Block("weathered_copper_door", builder() + public static final Block WEATHERED_COPPER_DOOR = register(new Block("weathered_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block WAXED_COPPER_DOOR = register(new Block("waxed_copper_door", builder() + public static final Block WAXED_COPPER_DOOR = register(new Block("waxed_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block WAXED_EXPOSED_COPPER_DOOR = register(new Block("waxed_exposed_copper_door", builder() + public static final Block WAXED_EXPOSED_COPPER_DOOR = register(new Block("waxed_exposed_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block WAXED_OXIDIZED_COPPER_DOOR = register(new Block("waxed_oxidized_copper_door", builder() + public static final Block WAXED_OXIDIZED_COPPER_DOOR = register(new Block("waxed_oxidized_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block WAXED_WEATHERED_COPPER_DOOR = register(new Block("waxed_weathered_copper_door", builder() + public static final Block WAXED_WEATHERED_COPPER_DOOR = register(new Block("waxed_weathered_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block COPPER_TRAPDOOR = register(new Block("copper_trapdoor", builder() + public static final Block COPPER_TRAPDOOR = register(new Block("copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block EXPOSED_COPPER_TRAPDOOR = register(new Block("exposed_copper_trapdoor", builder() + public static final Block EXPOSED_COPPER_TRAPDOOR = register(new Block("exposed_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block OXIDIZED_COPPER_TRAPDOOR = register(new Block("oxidized_copper_trapdoor", builder() + public static final Block OXIDIZED_COPPER_TRAPDOOR = register(new Block("oxidized_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block WEATHERED_COPPER_TRAPDOOR = register(new Block("weathered_copper_trapdoor", builder() + public static final Block WEATHERED_COPPER_TRAPDOOR = register(new Block("weathered_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block WAXED_COPPER_TRAPDOOR = register(new Block("waxed_copper_trapdoor", builder() + public static final Block WAXED_COPPER_TRAPDOOR = register(new Block("waxed_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block WAXED_EXPOSED_COPPER_TRAPDOOR = register(new Block("waxed_exposed_copper_trapdoor", builder() + public static final Block WAXED_EXPOSED_COPPER_TRAPDOOR = register(new Block("waxed_exposed_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block WAXED_OXIDIZED_COPPER_TRAPDOOR = register(new Block("waxed_oxidized_copper_trapdoor", builder() + public static final Block WAXED_OXIDIZED_COPPER_TRAPDOOR = register(new Block("waxed_oxidized_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block WAXED_WEATHERED_COPPER_TRAPDOOR = register(new Block("waxed_weathered_copper_trapdoor", builder() + public static final Block WAXED_WEATHERED_COPPER_TRAPDOOR = register(new Block("waxed_weathered_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block COPPER_GRATE = register(new Block("copper_grate", builder() + public static final Block COPPER_GRATE = register(new Block("copper_grate", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .booleanState(WATERLOGGED))); - public static final Block EXPOSED_COPPER_GRATE = register(new Block("exposed_copper_grate", builder() + public static final Block EXPOSED_COPPER_GRATE = register(new Block("exposed_copper_grate", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .booleanState(WATERLOGGED))); - public static final Block WEATHERED_COPPER_GRATE = register(new Block("weathered_copper_grate", builder() + public static final Block WEATHERED_COPPER_GRATE = register(new Block("weathered_copper_grate", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .booleanState(WATERLOGGED))); - public static final Block OXIDIZED_COPPER_GRATE = register(new Block("oxidized_copper_grate", builder() + public static final Block OXIDIZED_COPPER_GRATE = register(new Block("oxidized_copper_grate", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .booleanState(WATERLOGGED))); - public static final Block WAXED_COPPER_GRATE = register(new Block("waxed_copper_grate", builder() + public static final Block WAXED_COPPER_GRATE = register(new Block("waxed_copper_grate", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .booleanState(WATERLOGGED))); - public static final Block WAXED_EXPOSED_COPPER_GRATE = register(new Block("waxed_exposed_copper_grate", builder() + public static final Block WAXED_EXPOSED_COPPER_GRATE = register(new Block("waxed_exposed_copper_grate", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .booleanState(WATERLOGGED))); - public static final Block WAXED_WEATHERED_COPPER_GRATE = register(new Block("waxed_weathered_copper_grate", builder() + public static final Block WAXED_WEATHERED_COPPER_GRATE = register(new Block("waxed_weathered_copper_grate", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .booleanState(WATERLOGGED))); - public static final Block WAXED_OXIDIZED_COPPER_GRATE = register(new Block("waxed_oxidized_copper_grate", builder() + public static final Block WAXED_OXIDIZED_COPPER_GRATE = register(new Block("waxed_oxidized_copper_grate", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .booleanState(WATERLOGGED))); - public static final Block COPPER_BULB = register(new Block("copper_bulb", builder() + public static final Block COPPER_BULB = register(new Block("copper_bulb", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .booleanState(LIT) .booleanState(POWERED))); - public static final Block EXPOSED_COPPER_BULB = register(new Block("exposed_copper_bulb", builder() + public static final Block EXPOSED_COPPER_BULB = register(new Block("exposed_copper_bulb", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .booleanState(LIT) .booleanState(POWERED))); - public static final Block WEATHERED_COPPER_BULB = register(new Block("weathered_copper_bulb", builder() + public static final Block WEATHERED_COPPER_BULB = register(new Block("weathered_copper_bulb", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .booleanState(LIT) .booleanState(POWERED))); - public static final Block OXIDIZED_COPPER_BULB = register(new Block("oxidized_copper_bulb", builder() + public static final Block OXIDIZED_COPPER_BULB = register(new Block("oxidized_copper_bulb", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .booleanState(LIT) .booleanState(POWERED))); - public static final Block WAXED_COPPER_BULB = register(new Block("waxed_copper_bulb", builder() + public static final Block WAXED_COPPER_BULB = register(new Block("waxed_copper_bulb", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .booleanState(LIT) .booleanState(POWERED))); - public static final Block WAXED_EXPOSED_COPPER_BULB = register(new Block("waxed_exposed_copper_bulb", builder() + public static final Block WAXED_EXPOSED_COPPER_BULB = register(new Block("waxed_exposed_copper_bulb", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .booleanState(LIT) .booleanState(POWERED))); - public static final Block WAXED_WEATHERED_COPPER_BULB = register(new Block("waxed_weathered_copper_bulb", builder() + public static final Block WAXED_WEATHERED_COPPER_BULB = register(new Block("waxed_weathered_copper_bulb", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .booleanState(LIT) .booleanState(POWERED))); - public static final Block WAXED_OXIDIZED_COPPER_BULB = register(new Block("waxed_oxidized_copper_bulb", builder() + public static final Block WAXED_OXIDIZED_COPPER_BULB = register(new Block("waxed_oxidized_copper_bulb", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .booleanState(LIT) .booleanState(POWERED))); - public static final Block LIGHTNING_ROD = register(new Block("lightning_rod", builder() + public static final Block LIGHTNING_ROD = register(new Block("lightning_rod", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block POINTED_DRIPSTONE = register(new Block("pointed_dripstone", builder() + public static final Block POINTED_DRIPSTONE = register(new Block("pointed_dripstone", builder().destroyTime(1.5f) .enumState(DRIPSTONE_THICKNESS, "tip_merge", "tip", "frustum", "middle", "base") .enumState(VERTICAL_DIRECTION, Direction.UP, Direction.DOWN) .booleanState(WATERLOGGED))); - public static final Block DRIPSTONE_BLOCK = register(new Block("dripstone_block", builder())); + public static final Block DRIPSTONE_BLOCK = register(new Block("dripstone_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); public static final Block CAVE_VINES = register(new Block("cave_vines", builder() .intState(AGE_25, 0, 25) .booleanState(BERRIES))); @@ -2687,16 +2687,16 @@ public final class Blocks { public static final Block SPORE_BLOSSOM = register(new Block("spore_blossom", builder())); public static final Block AZALEA = register(new Block("azalea", builder())); public static final Block FLOWERING_AZALEA = register(new Block("flowering_azalea", builder())); - public static final Block MOSS_CARPET = register(new Block("moss_carpet", builder())); + public static final Block MOSS_CARPET = register(new Block("moss_carpet", builder().destroyTime(0.1f))); public static final Block PINK_PETALS = register(new Block("pink_petals", builder() .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .intState(FLOWER_AMOUNT, 1, 4))); - public static final Block MOSS_BLOCK = register(new Block("moss_block", builder())); - public static final Block BIG_DRIPLEAF = register(new Block("big_dripleaf", builder() + public static final Block MOSS_BLOCK = register(new Block("moss_block", builder().destroyTime(0.1f))); + public static final Block BIG_DRIPLEAF = register(new Block("big_dripleaf", builder().destroyTime(0.1f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(TILT, "none", "unstable", "partial", "full") .booleanState(WATERLOGGED))); - public static final Block BIG_DRIPLEAF_STEM = register(new Block("big_dripleaf_stem", builder() + public static final Block BIG_DRIPLEAF_STEM = register(new Block("big_dripleaf_stem", builder().destroyTime(0.1f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); public static final Block SMALL_DRIPLEAF = register(new Block("small_dripleaf", builder() @@ -2705,109 +2705,109 @@ public final class Blocks { .booleanState(WATERLOGGED))); public static final Block HANGING_ROOTS = register(new Block("hanging_roots", builder() .booleanState(WATERLOGGED))); - public static final Block ROOTED_DIRT = register(new Block("rooted_dirt", builder())); - public static final Block MUD = register(new Block("mud", builder())); - public static final Block DEEPSLATE = register(new Block("deepslate", builder() + public static final Block ROOTED_DIRT = register(new Block("rooted_dirt", builder().destroyTime(0.5f))); + public static final Block MUD = register(new Block("mud", builder().destroyTime(0.5f))); + public static final Block DEEPSLATE = register(new Block("deepslate", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block COBBLED_DEEPSLATE = register(new Block("cobbled_deepslate", builder())); - public static final Block COBBLED_DEEPSLATE_STAIRS = register(new Block("cobbled_deepslate_stairs", builder() + public static final Block COBBLED_DEEPSLATE = register(new Block("cobbled_deepslate", builder().requiresCorrectToolForDrops().destroyTime(3.5f))); + public static final Block COBBLED_DEEPSLATE_STAIRS = register(new Block("cobbled_deepslate_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block COBBLED_DEEPSLATE_SLAB = register(new Block("cobbled_deepslate_slab", builder() + public static final Block COBBLED_DEEPSLATE_SLAB = register(new Block("cobbled_deepslate_slab", builder().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block COBBLED_DEEPSLATE_WALL = register(new Block("cobbled_deepslate_wall", builder() + public static final Block COBBLED_DEEPSLATE_WALL = register(new Block("cobbled_deepslate_wall", builder().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(EAST_WALL, "none", "low", "tall") .enumState(NORTH_WALL, "none", "low", "tall") .enumState(SOUTH_WALL, "none", "low", "tall") .booleanState(UP) .booleanState(WATERLOGGED) .enumState(WEST_WALL, "none", "low", "tall"))); - public static final Block POLISHED_DEEPSLATE = register(new Block("polished_deepslate", builder())); - public static final Block POLISHED_DEEPSLATE_STAIRS = register(new Block("polished_deepslate_stairs", builder() + public static final Block POLISHED_DEEPSLATE = register(new Block("polished_deepslate", builder().requiresCorrectToolForDrops().destroyTime(3.5f))); + public static final Block POLISHED_DEEPSLATE_STAIRS = register(new Block("polished_deepslate_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block POLISHED_DEEPSLATE_SLAB = register(new Block("polished_deepslate_slab", builder() + public static final Block POLISHED_DEEPSLATE_SLAB = register(new Block("polished_deepslate_slab", builder().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block POLISHED_DEEPSLATE_WALL = register(new Block("polished_deepslate_wall", builder() + public static final Block POLISHED_DEEPSLATE_WALL = register(new Block("polished_deepslate_wall", builder().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(EAST_WALL, "none", "low", "tall") .enumState(NORTH_WALL, "none", "low", "tall") .enumState(SOUTH_WALL, "none", "low", "tall") .booleanState(UP) .booleanState(WATERLOGGED) .enumState(WEST_WALL, "none", "low", "tall"))); - public static final Block DEEPSLATE_TILES = register(new Block("deepslate_tiles", builder())); - public static final Block DEEPSLATE_TILE_STAIRS = register(new Block("deepslate_tile_stairs", builder() + public static final Block DEEPSLATE_TILES = register(new Block("deepslate_tiles", builder().requiresCorrectToolForDrops().destroyTime(3.5f))); + public static final Block DEEPSLATE_TILE_STAIRS = register(new Block("deepslate_tile_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block DEEPSLATE_TILE_SLAB = register(new Block("deepslate_tile_slab", builder() + public static final Block DEEPSLATE_TILE_SLAB = register(new Block("deepslate_tile_slab", builder().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block DEEPSLATE_TILE_WALL = register(new Block("deepslate_tile_wall", builder() + public static final Block DEEPSLATE_TILE_WALL = register(new Block("deepslate_tile_wall", builder().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(EAST_WALL, "none", "low", "tall") .enumState(NORTH_WALL, "none", "low", "tall") .enumState(SOUTH_WALL, "none", "low", "tall") .booleanState(UP) .booleanState(WATERLOGGED) .enumState(WEST_WALL, "none", "low", "tall"))); - public static final Block DEEPSLATE_BRICKS = register(new Block("deepslate_bricks", builder())); - public static final Block DEEPSLATE_BRICK_STAIRS = register(new Block("deepslate_brick_stairs", builder() + public static final Block DEEPSLATE_BRICKS = register(new Block("deepslate_bricks", builder().requiresCorrectToolForDrops().destroyTime(3.5f))); + public static final Block DEEPSLATE_BRICK_STAIRS = register(new Block("deepslate_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block DEEPSLATE_BRICK_SLAB = register(new Block("deepslate_brick_slab", builder() + public static final Block DEEPSLATE_BRICK_SLAB = register(new Block("deepslate_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block DEEPSLATE_BRICK_WALL = register(new Block("deepslate_brick_wall", builder() + public static final Block DEEPSLATE_BRICK_WALL = register(new Block("deepslate_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(EAST_WALL, "none", "low", "tall") .enumState(NORTH_WALL, "none", "low", "tall") .enumState(SOUTH_WALL, "none", "low", "tall") .booleanState(UP) .booleanState(WATERLOGGED) .enumState(WEST_WALL, "none", "low", "tall"))); - public static final Block CHISELED_DEEPSLATE = register(new Block("chiseled_deepslate", builder())); - public static final Block CRACKED_DEEPSLATE_BRICKS = register(new Block("cracked_deepslate_bricks", builder())); - public static final Block CRACKED_DEEPSLATE_TILES = register(new Block("cracked_deepslate_tiles", builder())); - public static final Block INFESTED_DEEPSLATE = register(new Block("infested_deepslate", builder() + public static final Block CHISELED_DEEPSLATE = register(new Block("chiseled_deepslate", builder().requiresCorrectToolForDrops().destroyTime(3.5f))); + public static final Block CRACKED_DEEPSLATE_BRICKS = register(new Block("cracked_deepslate_bricks", builder().requiresCorrectToolForDrops().destroyTime(3.5f))); + public static final Block CRACKED_DEEPSLATE_TILES = register(new Block("cracked_deepslate_tiles", builder().requiresCorrectToolForDrops().destroyTime(3.5f))); + public static final Block INFESTED_DEEPSLATE = register(new Block("infested_deepslate", builder().destroyTime(1.5f) .enumState(AXIS, Axis.VALUES))); - public static final Block SMOOTH_BASALT = register(new Block("smooth_basalt", builder())); - public static final Block RAW_IRON_BLOCK = register(new Block("raw_iron_block", builder())); - public static final Block RAW_COPPER_BLOCK = register(new Block("raw_copper_block", builder())); - public static final Block RAW_GOLD_BLOCK = register(new Block("raw_gold_block", builder())); + public static final Block SMOOTH_BASALT = register(new Block("smooth_basalt", builder().requiresCorrectToolForDrops().destroyTime(1.25f))); + public static final Block RAW_IRON_BLOCK = register(new Block("raw_iron_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f))); + public static final Block RAW_COPPER_BLOCK = register(new Block("raw_copper_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f))); + public static final Block RAW_GOLD_BLOCK = register(new Block("raw_gold_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f))); public static final Block POTTED_AZALEA_BUSH = register(new Block("potted_azalea_bush", builder())); public static final Block POTTED_FLOWERING_AZALEA_BUSH = register(new Block("potted_flowering_azalea_bush", builder())); - public static final Block OCHRE_FROGLIGHT = register(new Block("ochre_froglight", builder() + public static final Block OCHRE_FROGLIGHT = register(new Block("ochre_froglight", builder().destroyTime(0.3f) .enumState(AXIS, Axis.VALUES))); - public static final Block VERDANT_FROGLIGHT = register(new Block("verdant_froglight", builder() + public static final Block VERDANT_FROGLIGHT = register(new Block("verdant_froglight", builder().destroyTime(0.3f) .enumState(AXIS, Axis.VALUES))); - public static final Block PEARLESCENT_FROGLIGHT = register(new Block("pearlescent_froglight", builder() + public static final Block PEARLESCENT_FROGLIGHT = register(new Block("pearlescent_froglight", builder().destroyTime(0.3f) .enumState(AXIS, Axis.VALUES))); public static final Block FROGSPAWN = register(new Block("frogspawn", builder())); - public static final Block REINFORCED_DEEPSLATE = register(new Block("reinforced_deepslate", builder())); - public static final Block DECORATED_POT = register(new Block("decorated_pot", builder() + public static final Block REINFORCED_DEEPSLATE = register(new Block("reinforced_deepslate", builder().destroyTime(55.0f))); + public static final Block DECORATED_POT = register(new Block("decorated_pot", builder().setBlockEntity() .booleanState(CRACKED) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block CRAFTER = register(new Block("crafter", builder() + public static final Block CRAFTER = register(new Block("crafter", builder().setBlockEntity().destroyTime(1.5f) .booleanState(CRAFTING) .enumState(ORIENTATION, "down_east", "down_north", "down_south", "down_west", "up_east", "up_north", "up_south", "up_west", "west_up", "east_up", "north_up", "south_up") .booleanState(TRIGGERED))); - public static final Block TRIAL_SPAWNER = register(new Block("trial_spawner", builder() + public static final Block TRIAL_SPAWNER = register(new Block("trial_spawner", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(50.0f) .booleanState(OMINOUS) .enumState(TRIAL_SPAWNER_STATE, "inactive", "waiting_for_players", "active", "waiting_for_reward_ejection", "ejecting_reward", "cooldown"))); - public static final Block VAULT = register(new Block("vault", builder() + public static final Block VAULT = register(new Block("vault", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(50.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OMINOUS) .enumState(VAULT_STATE, "inactive", "active", "unlocking", "ejecting"))); - public static final Block HEAVY_CORE = register(new Block("heavy_core", builder() + public static final Block HEAVY_CORE = register(new Block("heavy_core", builder().destroyTime(10.0f) .booleanState(WATERLOGGED))); private static T register(T block) { diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java b/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java index 459f4a5af..84822ca16 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java @@ -41,10 +41,16 @@ public class Block { public static final int JAVA_AIR_ID = 0; private final String javaIdentifier; + private final boolean requiresCorrectToolForDrops; + private final boolean hasBlockEntity; + private final float destroyTime; private int javaId = -1; public Block(String javaIdentifier, Builder builder) { this.javaIdentifier = Identifier.formalize(javaIdentifier).intern(); + this.requiresCorrectToolForDrops = builder.requiresCorrectToolForDrops; + this.hasBlockEntity = builder.hasBlockEntity; + this.destroyTime = builder.destroyTime; builder.build(this); } @@ -52,6 +58,18 @@ public class Block { return javaIdentifier; } + public boolean requiresCorrectToolForDrops() { + return requiresCorrectToolForDrops; + } + + public boolean hasBlockEntity() { + return hasBlockEntity; + } + + public float destroyTime() { + return destroyTime; + } + public int javaId() { return javaId; } @@ -77,6 +95,9 @@ public class Block { public static final class Builder { private final Map, List>> states = new LinkedHashMap<>(); + private boolean requiresCorrectToolForDrops = false; + private boolean hasBlockEntity = false; + private float destroyTime; /** * For states that we're just tracking for mirroring Java states. @@ -107,6 +128,21 @@ public class Block { return this; } + public Builder requiresCorrectToolForDrops() { + this.requiresCorrectToolForDrops = true; + return this; + } + + public Builder setBlockEntity() { + this.hasBlockEntity = true; + return this; + } + + public Builder destroyTime(float destroyTime) { + this.destroyTime = destroyTime; + return this; + } + private void build(Block block) { if (states.isEmpty()) { BlockRegistries.BLOCK_STATES.get().add(new BlockState(block, BlockRegistries.BLOCK_STATES.get().size())); 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 ace110f78..b623bc043 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 @@ -51,6 +51,7 @@ 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.block.type.Block; import org.geysermc.geyser.level.physics.PistonBehavior; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.type.BlockMapping; @@ -565,6 +566,15 @@ public final class BlockRegistryPopulator { .isBlockEntity(javaBlockState.hasBlockEntity()) .build(); + Block.Builder builder = Block.builder() + .destroyTime(javaBlockState.blockHardness()); + if (!javaBlockState.canBreakWithHand()) { + builder.requiresCorrectToolForDrops(); + } + if (javaBlockState.hasBlockEntity()) { + builder.setBlockEntity(); + } + String cleanJavaIdentifier = BlockUtils.getCleanIdentifier(javaBlockState.identifier()); String bedrockIdentifier = customBlockState.block().identifier(); 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 38ac32214..6da354646 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,15 +25,16 @@ package org.geysermc.geyser.session.cache; -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; import org.geysermc.geyser.item.type.Item; +import org.geysermc.geyser.level.block.type.Block; 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 org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundUpdateTagsPacket; import javax.annotation.ParametersAreNonnullByDefault; import java.util.EnumMap; @@ -95,6 +96,17 @@ public final class TagCache { } } + /** + * @return true if the block tag is present and contains this block mapping's Java ID. + */ + public boolean is(BlockTag tag, Block block) { + IntList values = this.blocks.get(tag); + if (values != null) { + return values.contains(block.javaId()); + } + return false; + } + /** * @return true if the block tag is present and contains this block mapping's Java ID. */ 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 690fdb371..861f55731 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 @@ -40,6 +40,7 @@ import org.geysermc.geyser.entity.type.player.SessionPlayerEntity; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.type.Block; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.type.BlockMapping; @@ -160,7 +161,7 @@ public class BedrockActionTranslator extends PacketTranslator { @@ -42,7 +43,7 @@ public class JavaBlockDestructionTranslator extends PacketTranslator 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; + case "axe" -> session.getTagCache().is(BlockTag.AXE_EFFECTIVE, block); + case "hoe" -> session.getTagCache().is(BlockTag.HOE_EFFECTIVE, block); + case "pickaxe" -> session.getTagCache().is(BlockTag.PICKAXE_EFFECTIVE, block); + case "shears" -> session.getTagCache().is(BlockTag.LEAVES, block) || session.getTagCache().is(BlockTag.WOOL, block); + case "shovel" -> session.getTagCache().is(BlockTag.SHOVEL_EFFECTIVE, block); + case "sword" -> block == Blocks.COBWEB; default -> { session.getGeyser().getLogger().warning("Unknown tool type: " + itemToolType); yield false; @@ -71,7 +71,7 @@ public final class BlockUtils { }; } - private static boolean canToolTierBreakBlock(GeyserSession session, BlockMapping blockMapping, String toolTier) { + private static boolean canToolTierBreakBlock(GeyserSession session, Block block, String toolTier) { if (toolTier.equals("netherite") || toolTier.equals("diamond")) { // As of 1.17, these tiers can mine everything that is mineable return true; @@ -80,15 +80,15 @@ public final class BlockUtils { switch (toolTier) { // Use intentional fall-throughs to check each tier with this block default: - if (session.getTagCache().is(BlockTag.NEEDS_STONE_TOOL, blockMapping)) { + if (session.getTagCache().is(BlockTag.NEEDS_STONE_TOOL, block)) { return false; } case "stone": - if (session.getTagCache().is(BlockTag.NEEDS_IRON_TOOL, blockMapping)) { + if (session.getTagCache().is(BlockTag.NEEDS_IRON_TOOL, block)) { return false; } case "iron": - if (session.getTagCache().is(BlockTag.NEEDS_DIAMOND_TOOL, blockMapping)) { + if (session.getTagCache().is(BlockTag.NEEDS_DIAMOND_TOOL, block)) { return false; } } @@ -131,9 +131,9 @@ public final class BlockUtils { return 1.0 / speed; } - public static double getBreakTime(GeyserSession session, BlockMapping blockMapping, ItemMapping item, @Nullable DataComponents components, boolean isSessionPlayer) { - boolean isShearsEffective = session.getTagCache().is(BlockTag.LEAVES, blockMapping) || session.getTagCache().is(BlockTag.WOOL, blockMapping); //TODO called twice - boolean canHarvestWithHand = blockMapping.isCanBreakWithHand(); + public static double getBreakTime(GeyserSession session, Block block, ItemMapping item, @Nullable DataComponents components, boolean isSessionPlayer) { + boolean isShearsEffective = session.getTagCache().is(BlockTag.LEAVES, block) || session.getTagCache().is(BlockTag.WOOL, block); //TODO called twice + boolean canHarvestWithHand = !block.requiresCorrectToolForDrops(); String toolType = ""; String toolTier = ""; boolean correctTool = false; @@ -141,8 +141,8 @@ public final class BlockUtils { if (item.isTool()) { toolType = item.getToolType(); toolTier = item.getToolTier(); - correctTool = correctTool(session, blockMapping, toolType); - toolCanBreak = canToolTierBreakBlock(session, blockMapping, toolTier); + correctTool = correctTool(session, block, toolType); + toolCanBreak = canToolTierBreakBlock(session, block, toolTier); } int toolEfficiencyLevel = ItemUtils.getEnchantmentLevel(components, Enchantment.JavaEnchantment.EFFICIENCY); @@ -151,7 +151,7 @@ public final class BlockUtils { if (!isSessionPlayer) { // Another entity is currently mining; we have all the information we know - return calculateBreakTime(blockMapping.getHardness(), toolTier, canHarvestWithHand, correctTool, toolCanBreak, toolType, isShearsEffective, + return calculateBreakTime(block.destroyTime(), toolTier, canHarvestWithHand, correctTool, toolCanBreak, toolType, isShearsEffective, toolEfficiencyLevel, hasteLevel, miningFatigueLevel, false, true); } @@ -162,11 +162,11 @@ public final class BlockUtils { boolean insideOfWaterWithoutAquaAffinity = waterInEyes && ItemUtils.getEnchantmentLevel(session.getPlayerInventory().getItem(5).getComponents(), Enchantment.JavaEnchantment.AQUA_AFFINITY) < 1; - return calculateBreakTime(blockMapping.getHardness(), toolTier, canHarvestWithHand, correctTool, toolCanBreak, toolType, isShearsEffective, + return calculateBreakTime(block.destroyTime(), toolTier, canHarvestWithHand, correctTool, toolCanBreak, toolType, isShearsEffective, toolEfficiencyLevel, hasteLevel, miningFatigueLevel, insideOfWaterWithoutAquaAffinity, session.getPlayerEntity().isOnGround()); } - public static double getSessionBreakTime(GeyserSession session, BlockMapping blockMapping) { + public static double getSessionBreakTime(GeyserSession session, Block block) { PlayerInventory inventory = session.getPlayerInventory(); GeyserItemStack item = inventory.getItemInHand(); ItemMapping mapping = ItemMapping.AIR; @@ -175,7 +175,7 @@ public final class BlockUtils { mapping = item.getMapping(session); components = item.getComponents(); } - return getBreakTime(session, blockMapping, mapping, components, true); + return getBreakTime(session, block, mapping, components, true); } /** From 1cd0aad79fdb889ee989084cd1b0c05b1251e387 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Fri, 17 May 2024 15:02:12 -0400 Subject: [PATCH 011/233] Comment out snow collision Seems to be unnecessary as of 1.20.30. Will be deleted later if no problems are found! --- .../org/geysermc/geyser/translator/collision/SnowCollision.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/collision/SnowCollision.java b/core/src/main/java/org/geysermc/geyser/translator/collision/SnowCollision.java index fb83e357d..af2bcb7ea 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/collision/SnowCollision.java +++ b/core/src/main/java/org/geysermc/geyser/translator/collision/SnowCollision.java @@ -30,7 +30,7 @@ import org.geysermc.geyser.level.physics.BoundingBox; import org.geysermc.geyser.session.GeyserSession; @EqualsAndHashCode(callSuper = true) -@CollisionRemapper(regex = "^snow$", passDefaultBoxes = true, usesParams = true) +//@CollisionRemapper(regex = "^snow$", passDefaultBoxes = true, usesParams = true) TODO remove if no bugs are found. Seems fine with Bedrock 1.20.80 and 1.20.5 public class SnowCollision extends BlockCollision { private final int layers; From b010c500d84e59ee30c58c766b954a6dc2a45423 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 17 May 2024 22:21:01 +0200 Subject: [PATCH 012/233] Various entity fixes: Ensure TNT doesn't bug into the ground, reset player entity flags properly (#4670) * Various entity fixes * actually update the tnt entity position * revert bad diff --- .../geyser/entity/EntityDefinitions.java | 3 ++- .../geysermc/geyser/entity/type/Entity.java | 5 +++- .../geyser/entity/type/ExpOrbEntity.java | 7 +++++ .../geyser/entity/type/TNTEntity.java | 12 ++++++++- .../entity/type/player/PlayerEntity.java | 26 +++++++++++++++++++ .../type/player/SessionPlayerEntity.java | 10 ++----- 6 files changed, 52 insertions(+), 11 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 991b95571..21cc526dd 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -235,7 +235,7 @@ public final class EntityDefinitions { .addTranslator(MetadataType.BOOLEAN, (enderCrystalEntity, entityMetadata) -> enderCrystalEntity.setFlag(EntityFlag.SHOW_BOTTOM, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue())) // There is a base located on the ender crystal .build(); - EXPERIENCE_ORB = EntityDefinition.inherited(null, entityBase) + EXPERIENCE_ORB = EntityDefinition.inherited(ExpOrbEntity::new, entityBase) .type(EntityType.EXPERIENCE_ORB) .identifier("minecraft:xp_orb") .build(); @@ -297,6 +297,7 @@ public final class EntityDefinitions { TNT = EntityDefinition.inherited(TNTEntity::new, entityBase) .type(EntityType.TNT) .heightAndWidth(0.98f) + .offset(0.49f) .addTranslator(MetadataType.INT, TNTEntity::setFuseLength) .build(); 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 fecd72f67..a3f16875d 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 @@ -59,6 +59,9 @@ import java.util.*; @Getter @Setter public class Entity implements GeyserEntity { + + private static final boolean PRINT_ENTITY_SPAWN_DEBUG = Boolean.parseBoolean(System.getProperty("Geyser.PrintEntitySpawnDebug", "false")); + protected final GeyserSession session; protected int entityId; @@ -181,7 +184,7 @@ public class Entity implements GeyserEntity { flagsDirty = false; - if (session.getGeyser().getConfig().isDebugMode()) { + if (session.getGeyser().getConfig().isDebugMode() && PRINT_ENTITY_SPAWN_DEBUG) { EntityType type = definition.entityType(); String name = type != null ? type.name() : getClass().getSimpleName(); session.getGeyser().getLogger().debug("Spawned entity " + name + " at location " + position + " with id " + geyserId + " (java id " + entityId + ")"); diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ExpOrbEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ExpOrbEntity.java index 5a79a98b3..9f61bc961 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/ExpOrbEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/ExpOrbEntity.java @@ -27,11 +27,18 @@ package org.geysermc.geyser.entity.type; 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.EntityDefinitions; import org.geysermc.geyser.session.GeyserSession; +import java.util.UUID; + public class ExpOrbEntity extends Entity { + public ExpOrbEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition entityDefinition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { + this(session, 1, entityId, geyserId, position); + } + public ExpOrbEntity(GeyserSession session, int amount, int entityId, long geyserId, Vector3f position) { super(session, entityId, geyserId, null, EntityDefinitions.EXPERIENCE_ORB, position, Vector3f.ZERO, 0, 0, 0); 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 dca36cda0..47d97b8f7 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 @@ -39,7 +39,17 @@ public class TNTEntity extends Entity implements Tickable { private int currentTick; public TNTEntity(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); + super(session, entityId, geyserId, uuid, definition, position.add(0, definition.offset(), 0), motion, yaw, pitch, headYaw); + } + + @Override + public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, boolean isOnGround) { + super.moveRelative(relX, relY + definition.offset(), relZ, yaw, pitch, isOnGround); + } + + @Override + public void moveAbsolute(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) { + super.moveAbsolute(position.add(Vector3f.from(0, definition.offset(), 0)), yaw, pitch, headYaw, isOnGround, teleported); } public void setFuseLength(IntEntityMetadata entityMetadata) { 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 25040063e..4c67b882f 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 @@ -41,6 +41,7 @@ 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.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.packet.*; import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity; import org.geysermc.geyser.entity.EntityDefinitions; @@ -166,6 +167,31 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity { session.sendUpstreamPacket(addPlayerPacket); } + @Override + public void despawnEntity() { + super.despawnEntity(); + + // Since we re-use player entities: Clear flags, held item, etc + this.resetMetadata(); + this.hand = ItemData.AIR; + this.offhand = ItemData.AIR; + this.boots = ItemData.AIR; + this.leggings = ItemData.AIR; + this.chestplate = ItemData.AIR; + this.helmet = ItemData.AIR; + } + + public void resetMetadata() { + // Reset all metadata to their default values + // This is used when a player respawns + this.flags.clear(); + this.initializeMetadata(); + + // Explicitly reset all metadata not handled by initializeMetadata + setParrot(null, true); + setParrot(null, false); + } + public void sendPlayer() { if (session.getEntityCache().getPlayerEntity(uuid) == null) return; 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 e10adb134..533ca3c59 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 @@ -264,19 +264,13 @@ public class SessionPlayerEntity extends PlayerEntity { super.setAbsorptionHearts(entityMetadata); } + @Override public void resetMetadata() { - // Reset all metadata to their default values - // This is used when a player respawns - this.flags.clear(); - this.initializeMetadata(); + super.resetMetadata(); // 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(); From 5ebb6ef0d66ca5871c8c42adb245a2a3f48113d2 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 17 May 2024 22:48:46 +0200 Subject: [PATCH 013/233] Fix: using curly brackets in custom Minecraft locale overrides --- .../geyser/text/MinecraftTranslationRegistry.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) 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 b59b4db8e..67654360d 100644 --- a/core/src/main/java/org/geysermc/geyser/text/MinecraftTranslationRegistry.java +++ b/core/src/main/java/org/geysermc/geyser/text/MinecraftTranslationRegistry.java @@ -63,6 +63,13 @@ public class MinecraftTranslationRegistry extends TranslatableComponentRenderer< } } + // replace single quote instances which get lost in MessageFormat otherwise + localeString = localeString.replace("'", "''"); + + // Wrap all curly brackets with single quote inserts - fixes https://github.com/GeyserMC/Geyser/issues/4662 + localeString = localeString.replace("{", "'{") + .replace("}", "'}"); + // Replace the `%s` with numbered inserts `{0}` Pattern p = stringReplacement; Matcher m = p.matcher(localeString); @@ -83,8 +90,7 @@ public class MinecraftTranslationRegistry extends TranslatableComponentRenderer< } m.appendTail(sb); - // replace single quote instances which get lost in MessageFormat otherwise // Locale shouldn't need to be specific - dates for example will not be handled - return new MessageFormat(sb.toString().replace("'", "''"), Locale.ROOT); + return new MessageFormat(sb.toString(), Locale.ROOT); } } From 06dc0d1ca83f820ec9fed233a7998eeead888363 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Fri, 17 May 2024 17:52:19 -0400 Subject: [PATCH 014/233] Collisions without BlockMapping --- .../java/org/geysermc/geyser/GeyserImpl.java | 2 - .../geyser/level/block/BlockStateValues.java | 3 - .../geyser/registry/BlockRegistries.java | 12 +-- .../geyser/registry/ListRegistry.java | 15 +++- .../loader/CollisionRegistryLoader.java | 76 +++++++++---------- .../populator/BlockRegistryPopulator.java | 11 +-- .../collision/CollisionRemapper.java | 6 -- .../collision/DirtPathCollision.java | 3 +- .../translator/collision/DoorCollision.java | 22 +++--- .../GlassPaneAndIronBarsCollision.java | 21 ++--- .../collision/ScaffoldingCollision.java | 3 +- .../translator/collision/SolidCollision.java | 3 +- .../collision/TrapdoorCollision.java | 47 ++++-------- core/src/main/resources/mappings | 2 +- 14 files changed, 100 insertions(+), 126 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 4f572ef63..e7237e8bf 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -69,7 +69,6 @@ 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.level.block.Blocks; import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.network.netty.GeyserServer; import org.geysermc.geyser.registry.BlockRegistries; @@ -258,7 +257,6 @@ public class GeyserImpl implements GeyserApi { VersionCheckUtils.checkForOutdatedJava(logger); - Blocks.VAULT.javaId(); for (int i = 0; i < BlockRegistries.JAVA_BLOCKS.get().length; i++) { String cleanIdentifier = BlockRegistries.JAVA_BLOCKS.get(i).getCleanJavaIdentifier(); String newIdentifier = BlockRegistries.BLOCK_STATES.get(i).block().javaIdentifier(); 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 205486ced..e2a2cb5eb 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 @@ -69,9 +69,6 @@ public final class BlockStateValues { private static final Int2IntMap WATER_LEVEL = new Int2IntOpenHashMap(); private static final IntSet UPPER_DOORS = new IntOpenHashSet(); - public static final int JAVA_AIR_ID = 0; - - public static int JAVA_COBWEB_ID; public static int JAVA_FURNACE_ID; public static int JAVA_FURNACE_LIT_ID; public static int JAVA_HONEY_BLOCK_ID; 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 54a36dc12..416ab7793 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java +++ b/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java @@ -34,6 +34,7 @@ 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.JavaBlockState; +import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.registry.loader.CollisionRegistryLoader; @@ -82,19 +83,13 @@ public class BlockRegistries { /** * A mapped registry containing which holds block IDs to its {@link BlockCollision}. */ - public static final IntMappedRegistry COLLISIONS; + public static final ListRegistry COLLISIONS; /** * A mapped registry containing the Java identifiers to IDs. */ public static final MappedRegistry> JAVA_IDENTIFIER_TO_ID = MappedRegistry.create(RegistryLoaders.empty(Object2IntOpenHashMap::new)); - /** - * A registry which stores unique Java IDs to its clean identifier - * This is used in the statistics form. - */ - public static final ArrayRegistry CLEAN_JAVA_IDENTIFIERS = ArrayRegistry.create(RegistryLoaders.uninitialized()); - /** * A registry containing all the waterlogged blockstates. */ @@ -141,12 +136,13 @@ public class BlockRegistries { public static final SimpleMappedRegistry CUSTOM_SKULLS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new)); static { + Blocks.VAULT.javaId(); // FIXME 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); + COLLISIONS = ListRegistry.create(Pair.of("org.geysermc.geyser.translator.collision.CollisionRemapper", "mappings/collisions.nbt"), CollisionRegistryLoader::new); CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.VANILLA_REGISTRATION); CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.CUSTOM_REGISTRATION); BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.INIT_BEDROCK); diff --git a/core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java index bb5d2538c..d13c47ba8 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java +++ b/core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java @@ -29,6 +29,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.registry.loader.RegistryLoader; import java.util.List; +import java.util.function.Supplier; public class ListRegistry extends Registry> { /** @@ -98,6 +99,18 @@ public class ListRegistry extends Registry> { * @return a new registry with the given RegistryLoader supplier */ public static ListRegistry create(RegistryLoader> registryLoader) { - return new ListRegistry(null, registryLoader); + return new ListRegistry<>(null, registryLoader); + } + + /** + * Creates a new integer mapped registry with the given {@link RegistryLoader} and input. + * + * @param registryLoader the registry loader + * @param the input + * @param the type value + * @return a new registry with the given RegistryLoader supplier + */ + public static ListRegistry create(I input, Supplier>> registryLoader) { + return new ListRegistry<>(input, registryLoader.get()); } } 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 95e8bd2c1..7cf39b6d7 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 @@ -25,18 +25,19 @@ package org.geysermc.geyser.registry.loader; -import com.fasterxml.jackson.databind.node.ArrayNode; 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.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import lombok.AllArgsConstructor; import org.checkerframework.checker.nullness.qual.Nullable; +import org.cloudburstmc.nbt.NbtList; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtType; +import org.cloudburstmc.nbt.NbtUtils; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.level.physics.BoundingBox; import org.geysermc.geyser.registry.BlockRegistries; -import org.geysermc.geyser.registry.type.BlockMapping; import org.geysermc.geyser.translator.collision.BlockCollision; import org.geysermc.geyser.translator.collision.CollisionRemapper; import org.geysermc.geyser.translator.collision.OtherCollision; @@ -51,41 +52,43 @@ import java.util.regex.Pattern; /** * Loads collision data from the given resource path. */ -public class CollisionRegistryLoader extends MultiResourceRegistryLoader> { +public class CollisionRegistryLoader extends MultiResourceRegistryLoader> { @Override - public Int2ObjectMap load(Pair input) { - Int2ObjectMap collisions = new Int2ObjectOpenHashMap<>(); - + public List load(Pair input) { Map, CollisionInfo> annotationMap = new IdentityHashMap<>(); for (Class clazz : FileUtils.getGeneratedClassesForAnnotation(CollisionRemapper.class.getName())) { GeyserImpl.getInstance().getLogger().debug("Found annotated collision translator: " + clazz.getCanonicalName()); CollisionRemapper collisionRemapper = clazz.getAnnotation(CollisionRemapper.class); - annotationMap.put(clazz, new CollisionInfo(collisionRemapper, Pattern.compile(collisionRemapper.regex()), Pattern.compile(collisionRemapper.paramRegex()))); + annotationMap.put(clazz, new CollisionInfo(collisionRemapper, Pattern.compile(collisionRemapper.regex()))); } // Load collision mappings file + int[] indices; List collisionList; try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow(input.value())) { - ArrayNode collisionNode = (ArrayNode) GeyserImpl.JSON_MAPPER.readTree(stream); - collisionList = loadBoundingBoxes(collisionNode); + NbtMap collisionData = (NbtMap) NbtUtils.createGZIPReader(stream).readTag(); + indices = collisionData.getIntArray("indices"); + //SuppressWarnings unchecked + collisionList = loadBoundingBoxes(collisionData.getList("collisions", NbtType.LIST)); } catch (Exception e) { throw new AssertionError("Unable to load collision data", e); } - BlockMapping[] blockMappings = BlockRegistries.JAVA_BLOCKS.get(); + List blockStates = BlockRegistries.BLOCK_STATES.get(); + List collisions = new ObjectArrayList<>(blockStates.size()); // Map of unique collisions to its instance Map 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); + for (int i = 0; i < blockStates.size(); i++) { + BlockState state = blockStates.get(i); + if (state == null) { + GeyserImpl.getInstance().getLogger().warning("Missing block state for Java block " + i); continue; } - BlockCollision newCollision = instantiateCollision(blockMapping, annotationMap, collisionList); + BlockCollision newCollision = instantiateCollision(state, annotationMap, indices[i], collisionList); if (newCollision != null) { // If there's an existing instance equal to this one, use that instead @@ -97,33 +100,27 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader, CollisionInfo> annotationMap, List collisionList) { - String[] blockIdParts = mapping.getJavaIdentifier().split("\\["); - String blockName = blockIdParts[0].replace("minecraft:", ""); - String params = ""; - if (blockIdParts.length == 2) { - params = "[" + blockIdParts[1]; - } - int collisionIndex = mapping.getCollisionIndex(); + private @Nullable BlockCollision instantiateCollision(BlockState state, Map, CollisionInfo> annotationMap, int collisionIndex, List collisionList) { + String blockName = state.block().javaIdentifier().substring("minecraft:".length()); for (Map.Entry, CollisionInfo> collisionRemappers : annotationMap.entrySet()) { Class type = collisionRemappers.getKey(); CollisionInfo collisionInfo = collisionRemappers.getValue(); CollisionRemapper annotation = collisionInfo.collisionRemapper; - if (collisionInfo.pattern.matcher(blockName).find() && collisionInfo.paramsPattern.matcher(params).find()) { + if (collisionInfo.pattern.matcher(blockName).find()) { try { if (annotation.passDefaultBoxes()) { // Create an OtherCollision instance and get the bounding boxes BoundingBox[] defaultBoxes = collisionList.get(collisionIndex); - return (BlockCollision) type.getDeclaredConstructor(String.class, BoundingBox[].class).newInstance(params, defaultBoxes); + return (BlockCollision) type.getDeclaredConstructor(BlockState.class, BoundingBox[].class).newInstance(state, defaultBoxes); } else { - return (BlockCollision) type.getDeclaredConstructor(String.class).newInstance(params); + return (BlockCollision) type.getDeclaredConstructor(BlockState.class).newInstance(state); } } catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) { throw new RuntimeException(e); @@ -138,25 +135,25 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader loadBoundingBoxes(ArrayNode collisionNode) { + private List loadBoundingBoxes(List collisionNode) { List collisions = new ObjectArrayList<>(); for (int collisionIndex = 0; collisionIndex < collisionNode.size(); collisionIndex++) { - ArrayNode boundingBoxArray = (ArrayNode) collisionNode.get(collisionIndex); + @SuppressWarnings("unchecked") NbtList> boundingBoxArray = (NbtList>) collisionNode.get(collisionIndex); BoundingBox[] boundingBoxes = new BoundingBox[boundingBoxArray.size()]; for (int i = 0; i < boundingBoxArray.size(); i++) { - ArrayNode boxProperties = (ArrayNode) boundingBoxArray.get(i); - boundingBoxes[i] = new BoundingBox(boxProperties.get(0).asDouble(), - boxProperties.get(1).asDouble(), - boxProperties.get(2).asDouble(), - boxProperties.get(3).asDouble(), - boxProperties.get(4).asDouble(), - boxProperties.get(5).asDouble()); + NbtList boxProperties = boundingBoxArray.get(i); + boundingBoxes[i] = new BoundingBox(boxProperties.get(0), + boxProperties.get(1), + boxProperties.get(2), + boxProperties.get(3), + boxProperties.get(4), + boxProperties.get(5)); } // Sorting by lowest Y first fixes some bugs @@ -173,6 +170,5 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader cleanIdentifiers = new ArrayDeque<>(); int javaRuntimeId = -1; - int cobwebBlockId = -1; int furnaceRuntimeId = -1; int furnaceLitRuntimeId = -1; int honeyBlockRuntimeId = -1; @@ -485,10 +484,7 @@ public final class BlockRegistryPopulator { // 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()); - if (javaId.contains("cobweb")) { - cobwebBlockId = uniqueJavaId; - - } else if (javaId.startsWith("minecraft:furnace[facing=north")) { + if (javaId.startsWith("minecraft:furnace[facing=north")) { if (javaId.contains("lit=true")) { furnaceLitRuntimeId = javaRuntimeId; } else { @@ -507,11 +503,6 @@ public final class BlockRegistryPopulator { } } - if (cobwebBlockId == -1) { - throw new AssertionError("Unable to find cobwebs in palette"); - } - BlockStateValues.JAVA_COBWEB_ID = cobwebBlockId; - if (furnaceRuntimeId == -1) { throw new AssertionError("Unable to find furnace in palette"); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/collision/CollisionRemapper.java b/core/src/main/java/org/geysermc/geyser/translator/collision/CollisionRemapper.java index 6980968ab..fb93a14d5 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/collision/CollisionRemapper.java +++ b/core/src/main/java/org/geysermc/geyser/translator/collision/CollisionRemapper.java @@ -37,12 +37,6 @@ public @interface CollisionRemapper { */ String regex(); - /** - * Regex of block state parameters to apply this collision to - * Defaults to matching any value - */ - String paramRegex() default ".*"; - /** * Signals if a new instance needs to created for every block state */ diff --git a/core/src/main/java/org/geysermc/geyser/translator/collision/DirtPathCollision.java b/core/src/main/java/org/geysermc/geyser/translator/collision/DirtPathCollision.java index dcbad4758..d44187a0c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/collision/DirtPathCollision.java +++ b/core/src/main/java/org/geysermc/geyser/translator/collision/DirtPathCollision.java @@ -26,13 +26,14 @@ package org.geysermc.geyser.translator.collision; import lombok.EqualsAndHashCode; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.level.physics.BoundingBox; import org.geysermc.geyser.level.physics.CollisionManager; @EqualsAndHashCode(callSuper = true) @CollisionRemapper(regex = "^dirt_path$", passDefaultBoxes = true) public class DirtPathCollision extends BlockCollision { - public DirtPathCollision(String params, BoundingBox[] defaultBoxes) { + public DirtPathCollision(BlockState state, BoundingBox[] defaultBoxes) { super(defaultBoxes); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/collision/DoorCollision.java b/core/src/main/java/org/geysermc/geyser/translator/collision/DoorCollision.java index b47b187c4..33c85ce07 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/collision/DoorCollision.java +++ b/core/src/main/java/org/geysermc/geyser/translator/collision/DoorCollision.java @@ -26,6 +26,8 @@ package org.geysermc.geyser.translator.collision; import lombok.EqualsAndHashCode; +import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.level.physics.BoundingBox; import org.geysermc.geyser.session.GeyserSession; @@ -40,20 +42,18 @@ public class DoorCollision extends BlockCollision { */ private int facing; - public DoorCollision(String params, BoundingBox[] defaultBoxes) { + public DoorCollision(BlockState state, BoundingBox[] defaultBoxes) { super(defaultBoxes); - if (params.contains("facing=north")) { - facing = 1; - } else if (params.contains("facing=east")) { - facing = 2; - } else if (params.contains("facing=south")) { - facing = 3; - } else if (params.contains("facing=west")) { - facing = 4; - } + facing = switch (state.getValue(Properties.HORIZONTAL_FACING)) { + case NORTH -> 1; + case EAST -> 2; + case SOUTH -> 3; + case WEST -> 4; + default -> throw new IllegalStateException(); + }; // If the door is open it changes direction - if (params.contains("open=true")) { + if (state.getValue(Properties.OPEN)) { facing = facing % 2 + 1; } } 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 index 14439645a..35874348c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/collision/GlassPaneAndIronBarsCollision.java +++ b/core/src/main/java/org/geysermc/geyser/translator/collision/GlassPaneAndIronBarsCollision.java @@ -26,6 +26,8 @@ package org.geysermc.geyser.translator.collision; import lombok.EqualsAndHashCode; +import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.level.physics.BoundingBox; import org.geysermc.geyser.session.GeyserSession; @@ -44,24 +46,23 @@ public class GlassPaneAndIronBarsCollision extends BlockCollision { */ private int facing; - public GlassPaneAndIronBarsCollision(String params, BoundingBox[] defaultBoxes) { + public GlassPaneAndIronBarsCollision(BlockState state, BoundingBox[] defaultBoxes) { super(defaultBoxes); - //east=true,north=true,south=true,west=true - if (params.contains("north=true") && params.contains("east=true")) { + if (state.getValue(Properties.NORTH) && state.getValue(Properties.EAST)) { facing = 5; - } else if (params.contains("east=true") && params.contains("south=true")) { + } else if (state.getValue(Properties.EAST) && state.getValue(Properties.SOUTH)) { facing = 6; - } else if (params.contains("south=true") && params.contains("west=true")) { + } else if (state.getValue(Properties.SOUTH) && state.getValue(Properties.WEST)) { facing = 7; - } else if (params.contains("west=true") && params.contains("north=true")) { + } else if (state.getValue(Properties.WEST) && state.getValue(Properties.NORTH)) { facing = 8; - } else if (params.contains("north=true")) { + } else if (state.getValue(Properties.NORTH)) { facing = 1; - } else if (params.contains("east=true")) { + } else if (state.getValue(Properties.EAST)) { facing = 2; - } else if (params.contains("south=true")) { + } else if (state.getValue(Properties.SOUTH)) { facing = 3; - } else if (params.contains("west=true")) { + } else if (state.getValue(Properties.WEST)) { facing = 4; } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/collision/ScaffoldingCollision.java b/core/src/main/java/org/geysermc/geyser/translator/collision/ScaffoldingCollision.java index dfbd1c8b8..7449987c6 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/collision/ScaffoldingCollision.java +++ b/core/src/main/java/org/geysermc/geyser/translator/collision/ScaffoldingCollision.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.translator.collision; import lombok.EqualsAndHashCode; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.level.physics.BoundingBox; import org.geysermc.geyser.session.GeyserSession; @@ -35,7 +36,7 @@ import org.geysermc.geyser.session.GeyserSession; @EqualsAndHashCode(callSuper = true) @CollisionRemapper(regex = "^scaffolding$", usesParams = true, passDefaultBoxes = true) public class ScaffoldingCollision extends BlockCollision { - public ScaffoldingCollision(String params, BoundingBox[] defaultBoxes) { + public ScaffoldingCollision(BlockState state, BoundingBox[] defaultBoxes) { super(defaultBoxes); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/collision/SolidCollision.java b/core/src/main/java/org/geysermc/geyser/translator/collision/SolidCollision.java index 822202ff2..51d1038c0 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/collision/SolidCollision.java +++ b/core/src/main/java/org/geysermc/geyser/translator/collision/SolidCollision.java @@ -26,12 +26,13 @@ package org.geysermc.geyser.translator.collision; import lombok.EqualsAndHashCode; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.level.physics.BoundingBox; @EqualsAndHashCode(callSuper = true) @CollisionRemapper(regex = "shulker_box$") // These have no collision in the mappings as it depends on the NBT data public class SolidCollision extends BlockCollision { - public SolidCollision(String params) { + public SolidCollision(BlockState state) { super(new BoundingBox[] { new BoundingBox(0.5, 0.5, 0.5, 1, 1, 1) }); diff --git a/core/src/main/java/org/geysermc/geyser/translator/collision/TrapdoorCollision.java b/core/src/main/java/org/geysermc/geyser/translator/collision/TrapdoorCollision.java index 836c05711..909761166 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/collision/TrapdoorCollision.java +++ b/core/src/main/java/org/geysermc/geyser/translator/collision/TrapdoorCollision.java @@ -26,42 +26,27 @@ package org.geysermc.geyser.translator.collision; import lombok.EqualsAndHashCode; +import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.geyser.level.block.type.BlockState; 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.session.GeyserSession; @EqualsAndHashCode(callSuper = true) @CollisionRemapper(regex = "_trapdoor$", usesParams = true, passDefaultBoxes = true) public class TrapdoorCollision extends BlockCollision { - /** - * 1 = north - * 2 = east - * 3 = south - * 4 = west - * 5 = up - * 6 = down - */ - private int facing; + private final Direction facing; - public TrapdoorCollision(String params, BoundingBox[] defaultBoxes) { + public TrapdoorCollision(BlockState state, BoundingBox[] defaultBoxes) { super(defaultBoxes); - if (params.contains("open=true")) { - if (params.contains("facing=north")) { - facing = 1; - } else if (params.contains("facing=east")) { - facing = 2; - } else if (params.contains("facing=south")) { - facing = 3; - } else if (params.contains("facing=west")) { - facing = 4; - } + if (state.getValue(Properties.OPEN)) { + facing = state.getValue(Properties.HORIZONTAL_FACING); } else { - if (params.contains("half=bottom")) { - // Up - facing = 5; + if (state.getValue(Properties.HALF).equals("bottom")) { + facing = Direction.UP; } else { - // Down - facing = 6; + facing = Direction.DOWN; } } } @@ -72,22 +57,22 @@ public class TrapdoorCollision extends BlockCollision { // Check for door bug (doors are 0.1875 blocks thick on Java but 0.1825 blocks thick on Bedrock) if (this.checkIntersection(x, y, z, playerCollision)) { switch (facing) { - case 1: // North + case NORTH: playerCollision.setMiddleZ(z + 0.5125); break; - case 2: // East + case EAST: playerCollision.setMiddleX(x + 0.5125); break; - case 3: // South + case SOUTH: playerCollision.setMiddleZ(z + 0.4875); break; - case 4: // West + case WEST: playerCollision.setMiddleX(x + 0.4875); break; - case 5: + case UP: // Up-facing trapdoors are handled by the step-up check break; - case 6: // Down + case DOWN: // (top y of trap door) - (trap door thickness) = top y of player playerCollision.setMiddleY(y + 1 - (3.0 / 16.0) - playerCollision.getSizeY() / 2.0 - CollisionManager.COLLISION_TOLERANCE); break; diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings index 7c01501ed..6b661f0d5 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 7c01501ed6a0ee8848a66d729000539f2661f785 +Subproject commit 6b661f0d517d895aebc1f55a25d2c86f033beb1d From beef01f3fc96befb0558b070c34dd04400fb4eec Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Fri, 17 May 2024 20:55:34 -0400 Subject: [PATCH 015/233] Pistons now use the new block stuff --- .../erosion/GeyserboundPacketHandlerImpl.java | 13 +- .../geysermc/geyser/level/WorldManager.java | 9 + .../geyser/level/block/BlockStateValues.java | 98 +-- .../geysermc/geyser/level/block/Blocks.java | 704 +++++++++--------- .../level/block/property/Properties.java | 2 +- .../geyser/level/block/type/Block.java | 86 +++ .../geyser/level/block/type/BlockState.java | 4 + .../level/block/type/CauldronBlock.java | 51 ++ .../geyser/level/block/type/ChestBlock.java | 52 ++ .../geyser/level/block/type/DoorBlock.java | 50 ++ .../block/type/FlowerPotBlock.java} | 74 +- .../geyser/level/block/type/LecternBlock.java | 61 ++ .../level/block/type/MovingPistonBlock.java | 42 ++ .../geyser/level/block/type/PistonBlock.java | 47 ++ .../geyser/level/block/type/SkullBlock.java | 54 ++ .../populator/BlockRegistryPopulator.java | 40 +- .../geyser/registry/type/BlockMapping.java | 15 +- .../geyser/registry/type/BlockMappings.java | 5 + .../geyser/session/cache/TagCache.java | 12 - .../geyser/session/cache/WorldCache.java | 2 +- ...a => BedrockChunkWantsBlockEntityTag.java} | 30 +- .../block/entity/BedrockOnlyBlockEntity.java | 82 -- .../DoubleChestBlockEntityTranslator.java | 21 +- .../level/block/entity/PistonBlockEntity.java | 85 +-- .../BedrockBlockPickRequestTranslator.java | 4 +- .../java/level/JavaBlockEventTranslator.java | 22 +- .../JavaLevelChunkWithLightTranslator.java | 19 +- .../geyser/util/BlockEntityUtils.java | 12 - .../org/geysermc/geyser/util/ChunkUtils.java | 111 +-- 29 files changed, 978 insertions(+), 829 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/type/CauldronBlock.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/type/ChestBlock.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/type/DoorBlock.java rename core/src/main/java/org/geysermc/geyser/{translator/level/block/entity/FlowerPotBlockEntityTranslator.java => level/block/type/FlowerPotBlock.java} (60%) create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/type/LecternBlock.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/type/MovingPistonBlock.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/type/PistonBlock.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/type/SkullBlock.java rename core/src/main/java/org/geysermc/geyser/translator/level/block/entity/{PistonBlockEntityTranslator.java => BedrockChunkWantsBlockEntityTag.java} (59%) delete mode 100644 core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedrockOnlyBlockEntity.java 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 b76dc0b85..6e22fd430 100644 --- a/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java +++ b/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java @@ -26,11 +26,12 @@ package org.geysermc.geyser.erosion; import io.netty.channel.Channel; +import it.unimi.dsi.fastutil.Pair; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.Object2IntArrayMap; -import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.Getter; import lombok.Setter; import org.cloudburstmc.math.vector.Vector3i; @@ -44,6 +45,7 @@ import org.geysermc.erosion.packet.backendbound.BackendboundPacket; import org.geysermc.erosion.packet.geyserbound.*; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.type.Block; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.level.physics.Direction; import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.session.GeyserSession; @@ -153,9 +155,10 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke var stream = packet.getAttachedBlocks() .object2IntEntrySet() .stream() - .filter(entry -> BlockStateValues.canPistonMoveBlock(entry.getIntValue(), isExtend)); - Object2IntMap attachedBlocks = new Object2IntArrayMap<>(); - stream.forEach(entry -> attachedBlocks.put(entry.getKey(), entry.getIntValue())); + .map(entry -> Pair.of(entry.getKey(), BlockState.of(entry.getIntValue()))) + .filter(pair -> BlockStateValues.canPistonMoveBlock(pair.value(), isExtend)); + Object2ObjectMap attachedBlocks = new Object2ObjectOpenHashMap<>(); + stream.forEach(pair -> attachedBlocks.put(pair.key(), pair.value())); session.executeInEventLoop(() -> { PistonCache pistonCache = session.getPistonCache(); 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 cd6c9e824..5edce21dc 100644 --- a/core/src/main/java/org/geysermc/geyser/level/WorldManager.java +++ b/core/src/main/java/org/geysermc/geyser/level/WorldManager.java @@ -33,6 +33,7 @@ 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.level.block.type.BlockState; 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.DataComponent; @@ -58,6 +59,14 @@ import java.util.function.Function; */ public abstract class WorldManager { + public final BlockState blockAt(GeyserSession session, Vector3i vector3i) { + return BlockState.of(this.getBlockAt(session, vector3i)); + } + + public BlockState blockAt(GeyserSession session, int x, int y, int z) { + return BlockState.of(this.getBlockAt(session, x, y, z)); + } + /** * Gets the Java block state at the specified location * 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 e2a2cb5eb..a64e5c1c8 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 @@ -29,12 +29,14 @@ import com.fasterxml.jackson.databind.JsonNode; import it.unimi.dsi.fastutil.ints.*; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.level.block.type.Block; +import org.geysermc.geyser.level.block.type.BlockState; +import org.geysermc.geyser.level.block.type.PistonBlock; import org.geysermc.geyser.level.physics.Direction; import org.geysermc.geyser.level.physics.PistonBehavior; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.type.BlockMapping; -import org.geysermc.geyser.translator.level.block.entity.PistonBlockEntityTranslator; import org.geysermc.geyser.util.collection.FixedInt2ByteMap; import org.geysermc.geyser.util.collection.FixedInt2IntMap; import org.geysermc.geyser.util.collection.LecternHasBookMap; @@ -229,28 +231,6 @@ public final class BlockStateValues { return BANNER_COLORS.getOrDefault(state, -1); } - /** - * Bed colors are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock. - * This gives a byte color that Bedrock can use - Bedrock needs a byte in the final tag. - * - * @param state BlockState of the block - * @return Bed color byte or -1 if no color - */ - public static byte getBedColor(int state) { - 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); - } - /** * @return if this Java block state is a non-empty non-water cauldron */ @@ -341,18 +321,6 @@ public final class BlockStateValues { return PISTON_HEADS.getOrDefault(direction, Block.JAVA_AIR_ID); } - /** - * Check if a block is a minecraft:moving_piston - * This is used in ChunkUtils to prevent them from being placed as it causes - * pistons to flicker and it is not needed - * - * @param state Block state of the block - * @return True if the block is a moving_piston - */ - public static boolean isMovingPiston(int state) { - return MOVING_PISTONS.contains(state); - } - /** * This is used in GeyserPistonEvents.java and accepts minecraft:piston, * minecraft:sticky_piston, and minecraft:moving_piston. @@ -371,8 +339,9 @@ public final class BlockStateValues { * @param state The block state * @return True if the block sticks to adjacent blocks */ - public static boolean isBlockSticky(int state) { - return state == JAVA_SLIME_BLOCK_ID || state == JAVA_HONEY_BLOCK_ID; + public static boolean isBlockSticky(BlockState state) { + Block block = state.block(); + return block == Blocks.SLIME_BLOCK || block == Blocks.HONEY_BLOCK; } /** @@ -382,13 +351,13 @@ public final class BlockStateValues { * @param stateB The block state of block b * @return True if the blocks are attached to each other */ - public static boolean isBlockAttached(int stateA, int stateB) { + public static boolean isBlockAttached(BlockState stateA, BlockState stateB) { boolean aSticky = isBlockSticky(stateA); boolean bSticky = isBlockSticky(stateB); if (aSticky && bSticky) { // Only matching sticky blocks are attached together // Honey + Honey & Slime + Slime - return stateA == stateB; + return stateA.block() == stateB.block(); } return aSticky || bSticky; } @@ -397,27 +366,30 @@ public final class BlockStateValues { * @param state The block state of the block * @return true if a piston can break the block */ - public static boolean canPistonDestroyBlock(int state) { - return BlockRegistries.JAVA_BLOCKS.getOrDefault(state, BlockMapping.DEFAULT).getPistonBehavior() == PistonBehavior.DESTROY; + public static boolean canPistonDestroyBlock(BlockState state) { + return state.block().pushReaction() == PistonBehavior.DESTROY; } - public static boolean canPistonMoveBlock(int javaId, boolean isPushing) { - if (javaId == Block.JAVA_AIR_ID) { + public static boolean canPistonMoveBlock(BlockState state, boolean isPushing) { + Block block = state.block(); + if (block == Blocks.AIR) { return true; } - // Pistons can only be moved if they aren't extended - if (PistonBlockEntityTranslator.isBlock(javaId)) { - return !PISTON_VALUES.get(javaId); - } - BlockMapping block = BlockRegistries.JAVA_BLOCKS.getOrDefault(javaId, BlockMapping.DEFAULT); - // Bedrock, End portal frames, etc. can't be moved - if (block.getHardness() == -1.0d) { + if (block == Blocks.OBSIDIAN || block == Blocks.CRYING_OBSIDIAN || block == Blocks.RESPAWN_ANCHOR || block == Blocks.REINFORCED_DEEPSLATE) { // Hardcoded as of 1.20.5 return false; } - return switch (block.getPistonBehavior()) { + // Pistons can only be moved if they aren't extended + if (block instanceof PistonBlock) { + return !state.getValue(Properties.EXTENDED); + } + // Bedrock, End portal frames, etc. can't be moved + if (block.destroyTime() == -1.0f) { + return false; + } + return switch (block.pushReaction()) { case BLOCK, DESTROY -> false; case PUSH_ONLY -> isPushing; // Glazed terracotta can only be pushed - default -> !block.isBlockEntity(); // Pistons can't move block entities + default -> !block.hasBlockEntity(); // Pistons can't move block entities }; } @@ -443,17 +415,6 @@ 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. @@ -464,17 +425,6 @@ public final class BlockStateValues { return SKULL_WALL_DIRECTIONS; } - /** - * Shulker box directions are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock. - * This gives a byte direction that Bedrock can use. - * - * @param state BlockState of the block - * @return Shulker direction value or -1 if no value - */ - public static byte getShulkerBoxDirection(int state) { - return SHULKERBOX_DIRECTIONS.getOrDefault(state, (byte) -1); - } - /** * Get the level of water from the block state. * diff --git a/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java index 1f9c9c162..142708dd9 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java @@ -25,11 +25,11 @@ package org.geysermc.geyser.level.block; -import org.geysermc.geyser.level.block.type.BannerBlock; -import org.geysermc.geyser.level.block.type.BedBlock; -import org.geysermc.geyser.level.block.type.Block; +import org.geysermc.geyser.level.block.property.ChestType; +import org.geysermc.geyser.level.block.type.*; import org.geysermc.geyser.level.physics.Axis; import org.geysermc.geyser.level.physics.Direction; +import org.geysermc.geyser.level.physics.PistonBehavior; import org.geysermc.geyser.registry.BlockRegistries; import static org.geysermc.geyser.level.block.property.Properties.*; @@ -62,36 +62,36 @@ public final class Blocks { public static final Block MANGROVE_PLANKS = register(new Block("mangrove_planks", builder().destroyTime(2.0f))); public static final Block BAMBOO_PLANKS = register(new Block("bamboo_planks", builder().destroyTime(2.0f))); public static final Block BAMBOO_MOSAIC = register(new Block("bamboo_mosaic", builder().destroyTime(2.0f))); - public static final Block OAK_SAPLING = register(new Block("oak_sapling", builder() + public static final Block OAK_SAPLING = register(new Block("oak_sapling", builder().pushReaction(PistonBehavior.DESTROY) .intState(STAGE, 0, 1))); - public static final Block SPRUCE_SAPLING = register(new Block("spruce_sapling", builder() + public static final Block SPRUCE_SAPLING = register(new Block("spruce_sapling", builder().pushReaction(PistonBehavior.DESTROY) .intState(STAGE, 0, 1))); - public static final Block BIRCH_SAPLING = register(new Block("birch_sapling", builder() + public static final Block BIRCH_SAPLING = register(new Block("birch_sapling", builder().pushReaction(PistonBehavior.DESTROY) .intState(STAGE, 0, 1))); - public static final Block JUNGLE_SAPLING = register(new Block("jungle_sapling", builder() + public static final Block JUNGLE_SAPLING = register(new Block("jungle_sapling", builder().pushReaction(PistonBehavior.DESTROY) .intState(STAGE, 0, 1))); - public static final Block ACACIA_SAPLING = register(new Block("acacia_sapling", builder() + public static final Block ACACIA_SAPLING = register(new Block("acacia_sapling", builder().pushReaction(PistonBehavior.DESTROY) .intState(STAGE, 0, 1))); - public static final Block CHERRY_SAPLING = register(new Block("cherry_sapling", builder() + public static final Block CHERRY_SAPLING = register(new Block("cherry_sapling", builder().pushReaction(PistonBehavior.DESTROY) .intState(STAGE, 0, 1))); - public static final Block DARK_OAK_SAPLING = register(new Block("dark_oak_sapling", builder() + public static final Block DARK_OAK_SAPLING = register(new Block("dark_oak_sapling", builder().pushReaction(PistonBehavior.DESTROY) .intState(STAGE, 0, 1))); - public static final Block MANGROVE_PROPAGULE = register(new Block("mangrove_propagule", builder() + public static final Block MANGROVE_PROPAGULE = register(new Block("mangrove_propagule", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_4, 0, 4) .booleanState(HANGING) .intState(STAGE, 0, 1) .booleanState(WATERLOGGED))); public static final Block BEDROCK = register(new Block("bedrock", builder().destroyTime(-1.0f))); - public static final Block WATER = register(new Block("water", builder().destroyTime(100.0f) + public static final Block WATER = register(new Block("water", builder().destroyTime(100.0f).pushReaction(PistonBehavior.DESTROY) .intState(LEVEL, 0, 15))); - public static final Block LAVA = register(new Block("lava", builder().destroyTime(100.0f) + public static final Block LAVA = register(new Block("lava", builder().destroyTime(100.0f).pushReaction(PistonBehavior.DESTROY) .intState(LEVEL, 0, 15))); public static final Block SAND = register(new Block("sand", builder().destroyTime(0.5f))); - public static final Block SUSPICIOUS_SAND = register(new Block("suspicious_sand", builder().setBlockEntity().destroyTime(0.25f) + public static final Block SUSPICIOUS_SAND = register(new Block("suspicious_sand", builder().setBlockEntity().destroyTime(0.25f).pushReaction(PistonBehavior.DESTROY) .intState(DUSTED, 0, 3))); public static final Block RED_SAND = register(new Block("red_sand", builder().destroyTime(0.5f))); public static final Block GRAVEL = register(new Block("gravel", builder().destroyTime(0.6f))); - public static final Block SUSPICIOUS_GRAVEL = register(new Block("suspicious_gravel", builder().setBlockEntity().destroyTime(0.25f) + public static final Block SUSPICIOUS_GRAVEL = register(new Block("suspicious_gravel", builder().setBlockEntity().destroyTime(0.25f).pushReaction(PistonBehavior.DESTROY) .intState(DUSTED, 0, 3))); public static final Block GOLD_ORE = register(new Block("gold_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); public static final Block DEEPSLATE_GOLD_ORE = register(new Block("deepslate_gold_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f))); @@ -172,43 +172,43 @@ public final class Blocks { .enumState(AXIS, Axis.VALUES))); public static final Block STRIPPED_MANGROVE_WOOD = register(new Block("stripped_mangrove_wood", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block OAK_LEAVES = register(new Block("oak_leaves", builder().destroyTime(0.2f) + public static final Block OAK_LEAVES = register(new Block("oak_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .intState(DISTANCE, 1, 7) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); - public static final Block SPRUCE_LEAVES = register(new Block("spruce_leaves", builder().destroyTime(0.2f) + public static final Block SPRUCE_LEAVES = register(new Block("spruce_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .intState(DISTANCE, 1, 7) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); - public static final Block BIRCH_LEAVES = register(new Block("birch_leaves", builder().destroyTime(0.2f) + public static final Block BIRCH_LEAVES = register(new Block("birch_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .intState(DISTANCE, 1, 7) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); - public static final Block JUNGLE_LEAVES = register(new Block("jungle_leaves", builder().destroyTime(0.2f) + public static final Block JUNGLE_LEAVES = register(new Block("jungle_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .intState(DISTANCE, 1, 7) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); - public static final Block ACACIA_LEAVES = register(new Block("acacia_leaves", builder().destroyTime(0.2f) + public static final Block ACACIA_LEAVES = register(new Block("acacia_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .intState(DISTANCE, 1, 7) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); - public static final Block CHERRY_LEAVES = register(new Block("cherry_leaves", builder().destroyTime(0.2f) + public static final Block CHERRY_LEAVES = register(new Block("cherry_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .intState(DISTANCE, 1, 7) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); - public static final Block DARK_OAK_LEAVES = register(new Block("dark_oak_leaves", builder().destroyTime(0.2f) + public static final Block DARK_OAK_LEAVES = register(new Block("dark_oak_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .intState(DISTANCE, 1, 7) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); - public static final Block MANGROVE_LEAVES = register(new Block("mangrove_leaves", builder().destroyTime(0.2f) + public static final Block MANGROVE_LEAVES = register(new Block("mangrove_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .intState(DISTANCE, 1, 7) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); - public static final Block AZALEA_LEAVES = register(new Block("azalea_leaves", builder().destroyTime(0.2f) + public static final Block AZALEA_LEAVES = register(new Block("azalea_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .intState(DISTANCE, 1, 7) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); - public static final Block FLOWERING_AZALEA_LEAVES = register(new Block("flowering_azalea_leaves", builder().destroyTime(0.2f) + public static final Block FLOWERING_AZALEA_LEAVES = register(new Block("flowering_azalea_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .intState(DISTANCE, 1, 7) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); @@ -228,67 +228,67 @@ public final class Blocks { .enumState(NOTEBLOCK_INSTRUMENT, "harp", "basedrum", "snare", "hat", "bass", "flute", "bell", "guitar", "chime", "xylophone", "iron_xylophone", "cow_bell", "didgeridoo", "bit", "banjo", "pling", "zombie", "skeleton", "creeper", "dragon", "wither_skeleton", "piglin", "custom_head") .intState(NOTE, 0, 24) .booleanState(POWERED))); - public static final Block WHITE_BED = register(new BedBlock("white_bed", 0, builder().setBlockEntity().destroyTime(0.2f) + public static final Block WHITE_BED = register(new BedBlock("white_bed", 0, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block ORANGE_BED = register(new BedBlock("orange_bed", 1, builder().setBlockEntity().destroyTime(0.2f) + public static final Block ORANGE_BED = register(new BedBlock("orange_bed", 1, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block MAGENTA_BED = register(new BedBlock("magenta_bed", 2, builder().setBlockEntity().destroyTime(0.2f) + public static final Block MAGENTA_BED = register(new BedBlock("magenta_bed", 2, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block LIGHT_BLUE_BED = register(new BedBlock("light_blue_bed", 3, builder().setBlockEntity().destroyTime(0.2f) + public static final Block LIGHT_BLUE_BED = register(new BedBlock("light_blue_bed", 3, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block YELLOW_BED = register(new BedBlock("yellow_bed", 4, builder().setBlockEntity().destroyTime(0.2f) + public static final Block YELLOW_BED = register(new BedBlock("yellow_bed", 4, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block LIME_BED = register(new BedBlock("lime_bed", 5, builder().setBlockEntity().destroyTime(0.2f) + public static final Block LIME_BED = register(new BedBlock("lime_bed", 5, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block PINK_BED = register(new BedBlock("pink_bed", 6, builder().setBlockEntity().destroyTime(0.2f) + public static final Block PINK_BED = register(new BedBlock("pink_bed", 6, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block GRAY_BED = register(new BedBlock("gray_bed", 7, builder().setBlockEntity().destroyTime(0.2f) + public static final Block GRAY_BED = register(new BedBlock("gray_bed", 7, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block LIGHT_GRAY_BED = register(new BedBlock("light_gray_bed", 8, builder().setBlockEntity().destroyTime(0.2f) + public static final Block LIGHT_GRAY_BED = register(new BedBlock("light_gray_bed", 8, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block CYAN_BED = register(new BedBlock("cyan_bed", 9, builder().setBlockEntity().destroyTime(0.2f) + public static final Block CYAN_BED = register(new BedBlock("cyan_bed", 9, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block PURPLE_BED = register(new BedBlock("purple_bed", 10, builder().setBlockEntity().destroyTime(0.2f) + public static final Block PURPLE_BED = register(new BedBlock("purple_bed", 10, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block BLUE_BED = register(new BedBlock("blue_bed", 11, builder().setBlockEntity().destroyTime(0.2f) + public static final Block BLUE_BED = register(new BedBlock("blue_bed", 11, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block BROWN_BED = register(new BedBlock("brown_bed", 12, builder().setBlockEntity().destroyTime(0.2f) + public static final Block BROWN_BED = register(new BedBlock("brown_bed", 12, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block GREEN_BED = register(new BedBlock("green_bed", 13, builder().setBlockEntity().destroyTime(0.2f) + public static final Block GREEN_BED = register(new BedBlock("green_bed", 13, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block RED_BED = register(new BedBlock("red_bed", 14, builder().setBlockEntity().destroyTime(0.2f) + public static final Block RED_BED = register(new BedBlock("red_bed", 14, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); - public static final Block BLACK_BED = register(new BedBlock("black_bed", 15, builder().setBlockEntity().destroyTime(0.2f) + public static final Block BLACK_BED = register(new BedBlock("black_bed", 15, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART, "head", "foot"))); @@ -300,20 +300,20 @@ public final class Blocks { .booleanState(POWERED) .enumState(RAIL_SHAPE_STRAIGHT, "north_south", "east_west", "ascending_east", "ascending_west", "ascending_north", "ascending_south") .booleanState(WATERLOGGED))); - public static final Block STICKY_PISTON = register(new Block("sticky_piston", builder().destroyTime(1.5f) + public static final Block STICKY_PISTON = register(new PistonBlock("sticky_piston", builder().destroyTime(1.5f).pushReaction(PistonBehavior.BLOCK) .booleanState(EXTENDED) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block COBWEB = register(new Block("cobweb", builder().requiresCorrectToolForDrops().destroyTime(4.0f))); - public static final Block SHORT_GRASS = register(new Block("short_grass", builder())); - public static final Block FERN = register(new Block("fern", builder())); - public static final Block DEAD_BUSH = register(new Block("dead_bush", builder())); - public static final Block SEAGRASS = register(new Block("seagrass", builder())); - public static final Block TALL_SEAGRASS = register(new Block("tall_seagrass", builder() + public static final Block COBWEB = register(new Block("cobweb", builder().requiresCorrectToolForDrops().destroyTime(4.0f).pushReaction(PistonBehavior.DESTROY))); + public static final Block SHORT_GRASS = register(new Block("short_grass", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block FERN = register(new Block("fern", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block DEAD_BUSH = register(new Block("dead_bush", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block SEAGRASS = register(new Block("seagrass", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block TALL_SEAGRASS = register(new Block("tall_seagrass", builder().pushReaction(PistonBehavior.DESTROY) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); - public static final Block PISTON = register(new Block("piston", builder().destroyTime(1.5f) + public static final Block PISTON = register(new PistonBlock("piston", builder().destroyTime(1.5f).pushReaction(PistonBehavior.BLOCK) .booleanState(EXTENDED) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block PISTON_HEAD = register(new Block("piston_head", builder().destroyTime(1.5f) + public static final Block PISTON_HEAD = register(new Block("piston_head", builder().destroyTime(1.5f).pushReaction(PistonBehavior.BLOCK) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .booleanState(SHORT) .enumState(PISTON_TYPE, "normal", "sticky"))); @@ -333,25 +333,25 @@ public final class Blocks { public static final Block GREEN_WOOL = register(new Block("green_wool", builder().destroyTime(0.8f))); public static final Block RED_WOOL = register(new Block("red_wool", builder().destroyTime(0.8f))); public static final Block BLACK_WOOL = register(new Block("black_wool", builder().destroyTime(0.8f))); - public static final Block MOVING_PISTON = register(new Block("moving_piston", builder().setBlockEntity().destroyTime(-1.0f) + public static final Block MOVING_PISTON = register(new MovingPistonBlock("moving_piston", builder().setBlockEntity().destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .enumState(PISTON_TYPE, "normal", "sticky"))); - public static final Block DANDELION = register(new Block("dandelion", builder())); - public static final Block TORCHFLOWER = register(new Block("torchflower", builder())); - public static final Block POPPY = register(new Block("poppy", builder())); - public static final Block BLUE_ORCHID = register(new Block("blue_orchid", builder())); - public static final Block ALLIUM = register(new Block("allium", builder())); - public static final Block AZURE_BLUET = register(new Block("azure_bluet", builder())); - public static final Block RED_TULIP = register(new Block("red_tulip", builder())); - public static final Block ORANGE_TULIP = register(new Block("orange_tulip", builder())); - public static final Block WHITE_TULIP = register(new Block("white_tulip", builder())); - public static final Block PINK_TULIP = register(new Block("pink_tulip", builder())); - public static final Block OXEYE_DAISY = register(new Block("oxeye_daisy", builder())); - public static final Block CORNFLOWER = register(new Block("cornflower", builder())); - public static final Block WITHER_ROSE = register(new Block("wither_rose", builder())); - public static final Block LILY_OF_THE_VALLEY = register(new Block("lily_of_the_valley", builder())); - public static final Block BROWN_MUSHROOM = register(new Block("brown_mushroom", builder())); - public static final Block RED_MUSHROOM = register(new Block("red_mushroom", builder())); + public static final Block DANDELION = register(new Block("dandelion", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block TORCHFLOWER = register(new Block("torchflower", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POPPY = register(new Block("poppy", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block BLUE_ORCHID = register(new Block("blue_orchid", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block ALLIUM = register(new Block("allium", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block AZURE_BLUET = register(new Block("azure_bluet", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block RED_TULIP = register(new Block("red_tulip", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block ORANGE_TULIP = register(new Block("orange_tulip", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block WHITE_TULIP = register(new Block("white_tulip", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block PINK_TULIP = register(new Block("pink_tulip", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block OXEYE_DAISY = register(new Block("oxeye_daisy", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block CORNFLOWER = register(new Block("cornflower", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block WITHER_ROSE = register(new Block("wither_rose", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block LILY_OF_THE_VALLEY = register(new Block("lily_of_the_valley", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block BROWN_MUSHROOM = register(new Block("brown_mushroom", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block RED_MUSHROOM = register(new Block("red_mushroom", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block GOLD_BLOCK = register(new Block("gold_block", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); public static final Block IRON_BLOCK = register(new Block("iron_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f))); public static final Block BRICKS = register(new Block("bricks", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); @@ -368,28 +368,28 @@ public final class Blocks { .booleanState(CHISELED_BOOKSHELF_SLOT_5_OCCUPIED))); public static final Block MOSSY_COBBLESTONE = register(new Block("mossy_cobblestone", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); public static final Block OBSIDIAN = register(new Block("obsidian", builder().requiresCorrectToolForDrops().destroyTime(50.0f))); - public static final Block TORCH = register(new Block("torch", builder())); - public static final Block WALL_TORCH = register(new Block("wall_torch", builder() + public static final Block TORCH = register(new Block("torch", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block WALL_TORCH = register(new Block("wall_torch", builder().pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block FIRE = register(new Block("fire", builder() + public static final Block FIRE = register(new Block("fire", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_15, 0, 15) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(UP) .booleanState(WEST))); - public static final Block SOUL_FIRE = register(new Block("soul_fire", builder())); + public static final Block SOUL_FIRE = register(new Block("soul_fire", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block SPAWNER = register(new Block("spawner", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(5.0f))); public static final Block OAK_STAIRS = register(new Block("oak_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block CHEST = register(new Block("chest", builder().setBlockEntity().destroyTime(2.5f) + public static final Block CHEST = register(new ChestBlock("chest", builder().setBlockEntity().destroyTime(2.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(CHEST_TYPE, "single", "left", "right") + .enumState(CHEST_TYPE, ChestType.VALUES) .booleanState(WATERLOGGED))); - public static final Block REDSTONE_WIRE = register(new Block("redstone_wire", builder() + public static final Block REDSTONE_WIRE = register(new Block("redstone_wire", builder().pushReaction(PistonBehavior.DESTROY) .enumState(EAST_REDSTONE, "up", "side", "none") .enumState(NORTH_REDSTONE, "up", "side", "none") .intState(POWER, 0, 15) @@ -399,7 +399,7 @@ public final class Blocks { public static final Block DEEPSLATE_DIAMOND_ORE = register(new Block("deepslate_diamond_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f))); public static final Block DIAMOND_BLOCK = register(new Block("diamond_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f))); public static final Block CRAFTING_TABLE = register(new Block("crafting_table", builder().destroyTime(2.5f))); - public static final Block WHEAT = register(new Block("wheat", builder() + public static final Block WHEAT = register(new Block("wheat", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_7, 0, 7))); public static final Block FARMLAND = register(new Block("farmland", builder().destroyTime(0.6f) .intState(MOISTURE, 0, 7))); @@ -433,13 +433,13 @@ public final class Blocks { public static final Block BAMBOO_SIGN = register(new Block("bamboo_sign", builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15) .booleanState(WATERLOGGED))); - public static final Block OAK_DOOR = register(new Block("oak_door", builder().destroyTime(3.0f) + public static final Block OAK_DOOR = register(new DoorBlock("oak_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block LADDER = register(new Block("ladder", builder().destroyTime(0.4f) + public static final Block LADDER = register(new Block("ladder", builder().destroyTime(0.4f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); public static final Block RAIL = register(new Block("rail", builder().destroyTime(0.7f) @@ -554,57 +554,57 @@ public final class Blocks { public static final Block BAMBOO_WALL_HANGING_SIGN = register(new Block("bamboo_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block LEVER = register(new Block("lever", builder().destroyTime(0.5f) + public static final Block LEVER = register(new Block("lever", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block STONE_PRESSURE_PLATE = register(new Block("stone_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f) + public static final Block STONE_PRESSURE_PLATE = register(new Block("stone_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED))); - public static final Block IRON_DOOR = register(new Block("iron_door", builder().requiresCorrectToolForDrops().destroyTime(5.0f) + public static final Block IRON_DOOR = register(new DoorBlock("iron_door", builder().requiresCorrectToolForDrops().destroyTime(5.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block OAK_PRESSURE_PLATE = register(new Block("oak_pressure_plate", builder().destroyTime(0.5f) + public static final Block OAK_PRESSURE_PLATE = register(new Block("oak_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED))); - public static final Block SPRUCE_PRESSURE_PLATE = register(new Block("spruce_pressure_plate", builder().destroyTime(0.5f) + public static final Block SPRUCE_PRESSURE_PLATE = register(new Block("spruce_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED))); - public static final Block BIRCH_PRESSURE_PLATE = register(new Block("birch_pressure_plate", builder().destroyTime(0.5f) + public static final Block BIRCH_PRESSURE_PLATE = register(new Block("birch_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED))); - public static final Block JUNGLE_PRESSURE_PLATE = register(new Block("jungle_pressure_plate", builder().destroyTime(0.5f) + public static final Block JUNGLE_PRESSURE_PLATE = register(new Block("jungle_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED))); - public static final Block ACACIA_PRESSURE_PLATE = register(new Block("acacia_pressure_plate", builder().destroyTime(0.5f) + public static final Block ACACIA_PRESSURE_PLATE = register(new Block("acacia_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED))); - public static final Block CHERRY_PRESSURE_PLATE = register(new Block("cherry_pressure_plate", builder().destroyTime(0.5f) + public static final Block CHERRY_PRESSURE_PLATE = register(new Block("cherry_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED))); - public static final Block DARK_OAK_PRESSURE_PLATE = register(new Block("dark_oak_pressure_plate", builder().destroyTime(0.5f) + public static final Block DARK_OAK_PRESSURE_PLATE = register(new Block("dark_oak_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED))); - public static final Block MANGROVE_PRESSURE_PLATE = register(new Block("mangrove_pressure_plate", builder().destroyTime(0.5f) + public static final Block MANGROVE_PRESSURE_PLATE = register(new Block("mangrove_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED))); - public static final Block BAMBOO_PRESSURE_PLATE = register(new Block("bamboo_pressure_plate", builder().destroyTime(0.5f) + public static final Block BAMBOO_PRESSURE_PLATE = register(new Block("bamboo_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED))); public static final Block REDSTONE_ORE = register(new Block("redstone_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .booleanState(LIT))); public static final Block DEEPSLATE_REDSTONE_ORE = register(new Block("deepslate_redstone_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f) .booleanState(LIT))); - public static final Block REDSTONE_TORCH = register(new Block("redstone_torch", builder() + public static final Block REDSTONE_TORCH = register(new Block("redstone_torch", builder().pushReaction(PistonBehavior.DESTROY) .booleanState(LIT))); - public static final Block REDSTONE_WALL_TORCH = register(new Block("redstone_wall_torch", builder() + public static final Block REDSTONE_WALL_TORCH = register(new Block("redstone_wall_torch", builder().pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(LIT))); - public static final Block STONE_BUTTON = register(new Block("stone_button", builder().destroyTime(0.5f) + public static final Block STONE_BUTTON = register(new Block("stone_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block SNOW = register(new Block("snow", builder().requiresCorrectToolForDrops().destroyTime(0.1f) + public static final Block SNOW = register(new Block("snow", builder().requiresCorrectToolForDrops().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) .intState(LAYERS, 1, 8))); public static final Block ICE = register(new Block("ice", builder().destroyTime(0.5f))); public static final Block SNOW_BLOCK = register(new Block("snow_block", builder().requiresCorrectToolForDrops().destroyTime(0.2f))); - public static final Block CACTUS = register(new Block("cactus", builder().destroyTime(0.4f) + public static final Block CACTUS = register(new Block("cactus", builder().destroyTime(0.4f).pushReaction(PistonBehavior.DESTROY) .intState(AGE_15, 0, 15))); public static final Block CLAY = register(new Block("clay", builder().destroyTime(0.6f))); - public static final Block SUGAR_CANE = register(new Block("sugar_cane", builder() + public static final Block SUGAR_CANE = register(new Block("sugar_cane", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_15, 0, 15))); public static final Block JUKEBOX = register(new Block("jukebox", builder().setBlockEntity().destroyTime(2.0f) .booleanState(HAS_RECORD))); @@ -621,19 +621,19 @@ public final class Blocks { .enumState(AXIS, Axis.VALUES))); public static final Block POLISHED_BASALT = register(new Block("polished_basalt", builder().requiresCorrectToolForDrops().destroyTime(1.25f) .enumState(AXIS, Axis.VALUES))); - public static final Block SOUL_TORCH = register(new Block("soul_torch", builder())); - public static final Block SOUL_WALL_TORCH = register(new Block("soul_wall_torch", builder() + public static final Block SOUL_TORCH = register(new Block("soul_torch", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block SOUL_WALL_TORCH = register(new Block("soul_wall_torch", builder().pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); public static final Block GLOWSTONE = register(new Block("glowstone", builder().destroyTime(0.3f))); - public static final Block NETHER_PORTAL = register(new Block("nether_portal", builder().destroyTime(-1.0f) + public static final Block NETHER_PORTAL = register(new Block("nether_portal", builder().destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK) .enumState(HORIZONTAL_AXIS, Axis.X, Axis.Z))); - public static final Block CARVED_PUMPKIN = register(new Block("carved_pumpkin", builder().destroyTime(1.0f) + public static final Block CARVED_PUMPKIN = register(new Block("carved_pumpkin", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block JACK_O_LANTERN = register(new Block("jack_o_lantern", builder().destroyTime(1.0f) + public static final Block JACK_O_LANTERN = register(new Block("jack_o_lantern", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block CAKE = register(new Block("cake", builder().destroyTime(0.5f) + public static final Block CAKE = register(new Block("cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .intState(BITES, 0, 6))); - public static final Block REPEATER = register(new Block("repeater", builder() + public static final Block REPEATER = register(new Block("repeater", builder().pushReaction(PistonBehavior.DESTROY) .intState(DELAY, 1, 4) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(LOCKED) @@ -756,23 +756,23 @@ public final class Blocks { .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block PUMPKIN = register(new Block("pumpkin", builder().destroyTime(1.0f))); - public static final Block MELON = register(new Block("melon", builder().destroyTime(1.0f))); - public static final Block ATTACHED_PUMPKIN_STEM = register(new Block("attached_pumpkin_stem", builder() + public static final Block PUMPKIN = register(new Block("pumpkin", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY))); + public static final Block MELON = register(new Block("melon", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY))); + public static final Block ATTACHED_PUMPKIN_STEM = register(new Block("attached_pumpkin_stem", builder().pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block ATTACHED_MELON_STEM = register(new Block("attached_melon_stem", builder() + public static final Block ATTACHED_MELON_STEM = register(new Block("attached_melon_stem", builder().pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block PUMPKIN_STEM = register(new Block("pumpkin_stem", builder() + public static final Block PUMPKIN_STEM = register(new Block("pumpkin_stem", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_7, 0, 7))); - public static final Block MELON_STEM = register(new Block("melon_stem", builder() + public static final Block MELON_STEM = register(new Block("melon_stem", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_7, 0, 7))); - public static final Block VINE = register(new Block("vine", builder().destroyTime(0.2f) + public static final Block VINE = register(new Block("vine", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(UP) .booleanState(WEST))); - public static final Block GLOW_LICHEN = register(new Block("glow_lichen", builder().destroyTime(0.2f) + public static final Block GLOW_LICHEN = register(new Block("glow_lichen", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .booleanState(DOWN) .booleanState(EAST) .booleanState(NORTH) @@ -802,7 +802,7 @@ public final class Blocks { .booleanState(WATERLOGGED))); public static final Block MYCELIUM = register(new Block("mycelium", builder().destroyTime(0.6f) .booleanState(SNOWY))); - public static final Block LILY_PAD = register(new Block("lily_pad", builder())); + public static final Block LILY_PAD = register(new Block("lily_pad", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block NETHER_BRICKS = register(new Block("nether_bricks", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); public static final Block NETHER_BRICK_FENCE = register(new Block("nether_brick_fence", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .booleanState(EAST) @@ -815,28 +815,28 @@ public final class Blocks { .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block NETHER_WART = register(new Block("nether_wart", builder() + public static final Block NETHER_WART = register(new Block("nether_wart", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_3, 0, 3))); public static final Block ENCHANTING_TABLE = register(new Block("enchanting_table", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(5.0f))); public static final Block BREWING_STAND = register(new Block("brewing_stand", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(0.5f) .booleanState(HAS_BOTTLE_0) .booleanState(HAS_BOTTLE_1) .booleanState(HAS_BOTTLE_2))); - public static final Block CAULDRON = register(new Block("cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); + public static final Block CAULDRON = register(new CauldronBlock("cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); public static final Block WATER_CAULDRON = register(new Block("water_cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .intState(LEVEL_CAULDRON, 1, 3))); public static final Block LAVA_CAULDRON = register(new Block("lava_cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); public static final Block POWDER_SNOW_CAULDRON = register(new Block("powder_snow_cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .intState(LEVEL_CAULDRON, 1, 3))); - public static final Block END_PORTAL = register(new Block("end_portal", builder().setBlockEntity().destroyTime(-1.0f))); + public static final Block END_PORTAL = register(new Block("end_portal", builder().setBlockEntity().destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK))); public static final Block END_PORTAL_FRAME = register(new Block("end_portal_frame", builder().destroyTime(-1.0f) .booleanState(EYE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); public static final Block END_STONE = register(new Block("end_stone", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); - public static final Block DRAGON_EGG = register(new Block("dragon_egg", builder().destroyTime(3.0f))); + public static final Block DRAGON_EGG = register(new Block("dragon_egg", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY))); public static final Block REDSTONE_LAMP = register(new Block("redstone_lamp", builder().destroyTime(0.3f) .booleanState(LIT))); - public static final Block COCOA = register(new Block("cocoa", builder().destroyTime(0.2f) + public static final Block COCOA = register(new Block("cocoa", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .intState(AGE_2, 0, 2) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); public static final Block SANDSTONE_STAIRS = register(new Block("sandstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(0.8f) @@ -849,11 +849,11 @@ public final class Blocks { public static final Block ENDER_CHEST = register(new Block("ender_chest", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(22.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block TRIPWIRE_HOOK = register(new Block("tripwire_hook", builder() + public static final Block TRIPWIRE_HOOK = register(new Block("tripwire_hook", builder().pushReaction(PistonBehavior.DESTROY) .booleanState(ATTACHED) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block TRIPWIRE = register(new Block("tripwire", builder() + public static final Block TRIPWIRE = register(new Block("tripwire", builder().pushReaction(PistonBehavior.DESTROY) .booleanState(ATTACHED) .booleanState(DISARMED) .booleanState(EAST) @@ -895,131 +895,131 @@ public final class Blocks { .booleanState(UP) .booleanState(WATERLOGGED) .enumState(WEST_WALL, "none", "low", "tall"))); - public static final Block FLOWER_POT = register(new Block("flower_pot", builder())); - public static final Block POTTED_TORCHFLOWER = register(new Block("potted_torchflower", builder())); - public static final Block POTTED_OAK_SAPLING = register(new Block("potted_oak_sapling", builder())); - public static final Block POTTED_SPRUCE_SAPLING = register(new Block("potted_spruce_sapling", builder())); - public static final Block POTTED_BIRCH_SAPLING = register(new Block("potted_birch_sapling", builder())); - public static final Block POTTED_JUNGLE_SAPLING = register(new Block("potted_jungle_sapling", builder())); - public static final Block POTTED_ACACIA_SAPLING = register(new Block("potted_acacia_sapling", builder())); - public static final Block POTTED_CHERRY_SAPLING = register(new Block("potted_cherry_sapling", builder())); - public static final Block POTTED_DARK_OAK_SAPLING = register(new Block("potted_dark_oak_sapling", builder())); - public static final Block POTTED_MANGROVE_PROPAGULE = register(new Block("potted_mangrove_propagule", builder())); - public static final Block POTTED_FERN = register(new Block("potted_fern", builder())); - public static final Block POTTED_DANDELION = register(new Block("potted_dandelion", builder())); - public static final Block POTTED_POPPY = register(new Block("potted_poppy", builder())); - public static final Block POTTED_BLUE_ORCHID = register(new Block("potted_blue_orchid", builder())); - public static final Block POTTED_ALLIUM = register(new Block("potted_allium", builder())); - public static final Block POTTED_AZURE_BLUET = register(new Block("potted_azure_bluet", builder())); - public static final Block POTTED_RED_TULIP = register(new Block("potted_red_tulip", builder())); - public static final Block POTTED_ORANGE_TULIP = register(new Block("potted_orange_tulip", builder())); - public static final Block POTTED_WHITE_TULIP = register(new Block("potted_white_tulip", builder())); - public static final Block POTTED_PINK_TULIP = register(new Block("potted_pink_tulip", builder())); - public static final Block POTTED_OXEYE_DAISY = register(new Block("potted_oxeye_daisy", builder())); - public static final Block POTTED_CORNFLOWER = register(new Block("potted_cornflower", builder())); - public static final Block POTTED_LILY_OF_THE_VALLEY = register(new Block("potted_lily_of_the_valley", builder())); - public static final Block POTTED_WITHER_ROSE = register(new Block("potted_wither_rose", builder())); - public static final Block POTTED_RED_MUSHROOM = register(new Block("potted_red_mushroom", builder())); - public static final Block POTTED_BROWN_MUSHROOM = register(new Block("potted_brown_mushroom", builder())); - public static final Block POTTED_DEAD_BUSH = register(new Block("potted_dead_bush", builder())); - public static final Block POTTED_CACTUS = register(new Block("potted_cactus", builder())); - public static final Block CARROTS = register(new Block("carrots", builder() + public static final Block FLOWER_POT = register(new FlowerPotBlock("flower_pot", AIR, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_TORCHFLOWER = register(new FlowerPotBlock("potted_torchflower", TORCHFLOWER, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_OAK_SAPLING = register(new FlowerPotBlock("potted_oak_sapling", OAK_SAPLING, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_SPRUCE_SAPLING = register(new FlowerPotBlock("potted_spruce_sapling", SPRUCE_SAPLING, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_BIRCH_SAPLING = register(new FlowerPotBlock("potted_birch_sapling", BIRCH_SAPLING, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_JUNGLE_SAPLING = register(new FlowerPotBlock("potted_jungle_sapling", JUNGLE_SAPLING, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_ACACIA_SAPLING = register(new FlowerPotBlock("potted_acacia_sapling", ACACIA_SAPLING, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_CHERRY_SAPLING = register(new FlowerPotBlock("potted_cherry_sapling", CHERRY_SAPLING, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_DARK_OAK_SAPLING = register(new FlowerPotBlock("potted_dark_oak_sapling", DARK_OAK_SAPLING, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_MANGROVE_PROPAGULE = register(new FlowerPotBlock("potted_mangrove_propagule", MANGROVE_PROPAGULE, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_FERN = register(new FlowerPotBlock("potted_fern", FERN, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_DANDELION = register(new FlowerPotBlock("potted_dandelion", DANDELION, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_POPPY = register(new FlowerPotBlock("potted_poppy", POPPY, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_BLUE_ORCHID = register(new FlowerPotBlock("potted_blue_orchid", BLUE_ORCHID, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_ALLIUM = register(new FlowerPotBlock("potted_allium", ALLIUM, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_AZURE_BLUET = register(new FlowerPotBlock("potted_azure_bluet", AZURE_BLUET, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_RED_TULIP = register(new FlowerPotBlock("potted_red_tulip", RED_TULIP, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_ORANGE_TULIP = register(new FlowerPotBlock("potted_orange_tulip", ORANGE_TULIP, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_WHITE_TULIP = register(new FlowerPotBlock("potted_white_tulip", WHITE_TULIP, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_PINK_TULIP = register(new FlowerPotBlock("potted_pink_tulip", PINK_TULIP, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_OXEYE_DAISY = register(new FlowerPotBlock("potted_oxeye_daisy", OXEYE_DAISY, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_CORNFLOWER = register(new FlowerPotBlock("potted_cornflower", CORNFLOWER, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_LILY_OF_THE_VALLEY = register(new FlowerPotBlock("potted_lily_of_the_valley", LILY_OF_THE_VALLEY, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_WITHER_ROSE = register(new FlowerPotBlock("potted_wither_rose", WITHER_ROSE, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_RED_MUSHROOM = register(new FlowerPotBlock("potted_red_mushroom", RED_MUSHROOM, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_BROWN_MUSHROOM = register(new FlowerPotBlock("potted_brown_mushroom", BROWN_MUSHROOM, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_DEAD_BUSH = register(new FlowerPotBlock("potted_dead_bush", DEAD_BUSH, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_CACTUS = register(new FlowerPotBlock("potted_cactus", CACTUS, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block CARROTS = register(new Block("carrots", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_7, 0, 7))); - public static final Block POTATOES = register(new Block("potatoes", builder() + public static final Block POTATOES = register(new Block("potatoes", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_7, 0, 7))); - public static final Block OAK_BUTTON = register(new Block("oak_button", builder().destroyTime(0.5f) + public static final Block OAK_BUTTON = register(new Block("oak_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block SPRUCE_BUTTON = register(new Block("spruce_button", builder().destroyTime(0.5f) + public static final Block SPRUCE_BUTTON = register(new Block("spruce_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block BIRCH_BUTTON = register(new Block("birch_button", builder().destroyTime(0.5f) + public static final Block BIRCH_BUTTON = register(new Block("birch_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block JUNGLE_BUTTON = register(new Block("jungle_button", builder().destroyTime(0.5f) + public static final Block JUNGLE_BUTTON = register(new Block("jungle_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block ACACIA_BUTTON = register(new Block("acacia_button", builder().destroyTime(0.5f) + public static final Block ACACIA_BUTTON = register(new Block("acacia_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block CHERRY_BUTTON = register(new Block("cherry_button", builder().destroyTime(0.5f) + public static final Block CHERRY_BUTTON = register(new Block("cherry_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block DARK_OAK_BUTTON = register(new Block("dark_oak_button", builder().destroyTime(0.5f) + public static final Block DARK_OAK_BUTTON = register(new Block("dark_oak_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block MANGROVE_BUTTON = register(new Block("mangrove_button", builder().destroyTime(0.5f) + public static final Block MANGROVE_BUTTON = register(new Block("mangrove_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block BAMBOO_BUTTON = register(new Block("bamboo_button", builder().destroyTime(0.5f) + public static final Block BAMBOO_BUTTON = register(new Block("bamboo_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block SKELETON_SKULL = register(new Block("skeleton_skull", builder().setBlockEntity().destroyTime(1.0f) + public static final Block SKELETON_SKULL = register(new SkullBlock("skeleton_skull", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) .intState(ROTATION_16, 0, 15))); - public static final Block SKELETON_WALL_SKULL = register(new Block("skeleton_wall_skull", builder().setBlockEntity().destroyTime(1.0f) + public static final Block SKELETON_WALL_SKULL = register(new SkullBlock("skeleton_wall_skull", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block WITHER_SKELETON_SKULL = register(new Block("wither_skeleton_skull", builder().setBlockEntity().destroyTime(1.0f) + public static final Block WITHER_SKELETON_SKULL = register(new SkullBlock("wither_skeleton_skull", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) .intState(ROTATION_16, 0, 15))); - public static final Block WITHER_SKELETON_WALL_SKULL = register(new Block("wither_skeleton_wall_skull", builder().setBlockEntity().destroyTime(1.0f) + public static final Block WITHER_SKELETON_WALL_SKULL = register(new SkullBlock("wither_skeleton_wall_skull", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block ZOMBIE_HEAD = register(new Block("zombie_head", builder().setBlockEntity().destroyTime(1.0f) + public static final Block ZOMBIE_HEAD = register(new SkullBlock("zombie_head", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) .intState(ROTATION_16, 0, 15))); - public static final Block ZOMBIE_WALL_HEAD = register(new Block("zombie_wall_head", builder().setBlockEntity().destroyTime(1.0f) + public static final Block ZOMBIE_WALL_HEAD = register(new SkullBlock("zombie_wall_head", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block PLAYER_HEAD = register(new Block("player_head", builder().setBlockEntity().destroyTime(1.0f) + public static final Block PLAYER_HEAD = register(new SkullBlock("player_head", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) .intState(ROTATION_16, 0, 15))); - public static final Block PLAYER_WALL_HEAD = register(new Block("player_wall_head", builder().setBlockEntity().destroyTime(1.0f) + public static final Block PLAYER_WALL_HEAD = register(new SkullBlock("player_wall_head", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block CREEPER_HEAD = register(new Block("creeper_head", builder().setBlockEntity().destroyTime(1.0f) + public static final Block CREEPER_HEAD = register(new SkullBlock("creeper_head", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) .intState(ROTATION_16, 0, 15))); - public static final Block CREEPER_WALL_HEAD = register(new Block("creeper_wall_head", builder().setBlockEntity().destroyTime(1.0f) + public static final Block CREEPER_WALL_HEAD = register(new SkullBlock("creeper_wall_head", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block DRAGON_HEAD = register(new Block("dragon_head", builder().setBlockEntity().destroyTime(1.0f) + public static final Block DRAGON_HEAD = register(new SkullBlock("dragon_head", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) .intState(ROTATION_16, 0, 15))); - public static final Block DRAGON_WALL_HEAD = register(new Block("dragon_wall_head", builder().setBlockEntity().destroyTime(1.0f) + public static final Block DRAGON_WALL_HEAD = register(new SkullBlock("dragon_wall_head", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block PIGLIN_HEAD = register(new Block("piglin_head", builder().setBlockEntity().destroyTime(1.0f) + public static final Block PIGLIN_HEAD = register(new SkullBlock("piglin_head", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) .intState(ROTATION_16, 0, 15))); - public static final Block PIGLIN_WALL_HEAD = register(new Block("piglin_wall_head", builder().setBlockEntity().destroyTime(1.0f) + public static final Block PIGLIN_WALL_HEAD = register(new SkullBlock("piglin_wall_head", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block ANVIL = register(new Block("anvil", builder().requiresCorrectToolForDrops().destroyTime(5.0f) + public static final Block ANVIL = register(new Block("anvil", builder().requiresCorrectToolForDrops().destroyTime(5.0f).pushReaction(PistonBehavior.BLOCK) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block CHIPPED_ANVIL = register(new Block("chipped_anvil", builder().requiresCorrectToolForDrops().destroyTime(5.0f) + public static final Block CHIPPED_ANVIL = register(new Block("chipped_anvil", builder().requiresCorrectToolForDrops().destroyTime(5.0f).pushReaction(PistonBehavior.BLOCK) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block DAMAGED_ANVIL = register(new Block("damaged_anvil", builder().requiresCorrectToolForDrops().destroyTime(5.0f) + public static final Block DAMAGED_ANVIL = register(new Block("damaged_anvil", builder().requiresCorrectToolForDrops().destroyTime(5.0f).pushReaction(PistonBehavior.BLOCK) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block TRAPPED_CHEST = register(new Block("trapped_chest", builder().setBlockEntity().destroyTime(2.5f) + public static final Block TRAPPED_CHEST = register(new ChestBlock("trapped_chest", builder().setBlockEntity().destroyTime(2.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(CHEST_TYPE, "single", "left", "right") + .enumState(CHEST_TYPE, ChestType.VALUES) .booleanState(WATERLOGGED))); - public static final Block LIGHT_WEIGHTED_PRESSURE_PLATE = register(new Block("light_weighted_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f) + public static final Block LIGHT_WEIGHTED_PRESSURE_PLATE = register(new Block("light_weighted_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .intState(POWER, 0, 15))); - public static final Block HEAVY_WEIGHTED_PRESSURE_PLATE = register(new Block("heavy_weighted_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f) + public static final Block HEAVY_WEIGHTED_PRESSURE_PLATE = register(new Block("heavy_weighted_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .intState(POWER, 0, 15))); - public static final Block COMPARATOR = register(new Block("comparator", builder().setBlockEntity() + public static final Block COMPARATOR = register(new Block("comparator", builder().setBlockEntity().pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(MODE_COMPARATOR, "compare", "subtract") .booleanState(POWERED))); @@ -1190,7 +1190,7 @@ public final class Blocks { .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); public static final Block SLIME_BLOCK = register(new Block("slime_block", builder())); - public static final Block BARRIER = register(new Block("barrier", builder().destroyTime(-1.0f) + public static final Block BARRIER = register(new Block("barrier", builder().destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK) .booleanState(WATERLOGGED))); public static final Block LIGHT = register(new Block("light", builder().destroyTime(-1.0f) .intState(LEVEL, 0, 15) @@ -1250,17 +1250,17 @@ public final class Blocks { public static final Block TERRACOTTA = register(new Block("terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f))); public static final Block COAL_BLOCK = register(new Block("coal_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f))); public static final Block PACKED_ICE = register(new Block("packed_ice", builder().destroyTime(0.5f))); - public static final Block SUNFLOWER = register(new Block("sunflower", builder() + public static final Block SUNFLOWER = register(new Block("sunflower", builder().pushReaction(PistonBehavior.DESTROY) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); - public static final Block LILAC = register(new Block("lilac", builder() + public static final Block LILAC = register(new Block("lilac", builder().pushReaction(PistonBehavior.DESTROY) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); - public static final Block ROSE_BUSH = register(new Block("rose_bush", builder() + public static final Block ROSE_BUSH = register(new Block("rose_bush", builder().pushReaction(PistonBehavior.DESTROY) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); - public static final Block PEONY = register(new Block("peony", builder() + public static final Block PEONY = register(new Block("peony", builder().pushReaction(PistonBehavior.DESTROY) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); - public static final Block TALL_GRASS = register(new Block("tall_grass", builder() + public static final Block TALL_GRASS = register(new Block("tall_grass", builder().pushReaction(PistonBehavior.DESTROY) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); - public static final Block LARGE_FERN = register(new Block("large_fern", builder() + public static final Block LARGE_FERN = register(new Block("large_fern", builder().pushReaction(PistonBehavior.DESTROY) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); public static final Block WHITE_BANNER = register(new BannerBlock("white_banner", 0, builder().setBlockEntity().destroyTime(1.0f) .intState(ROTATION_16, 0, 15))); @@ -1498,49 +1498,49 @@ public final class Blocks { .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block SPRUCE_DOOR = register(new Block("spruce_door", builder().destroyTime(3.0f) + public static final Block SPRUCE_DOOR = register(new DoorBlock("spruce_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block BIRCH_DOOR = register(new Block("birch_door", builder().destroyTime(3.0f) + public static final Block BIRCH_DOOR = register(new DoorBlock("birch_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block JUNGLE_DOOR = register(new Block("jungle_door", builder().destroyTime(3.0f) + public static final Block JUNGLE_DOOR = register(new DoorBlock("jungle_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block ACACIA_DOOR = register(new Block("acacia_door", builder().destroyTime(3.0f) + public static final Block ACACIA_DOOR = register(new DoorBlock("acacia_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block CHERRY_DOOR = register(new Block("cherry_door", builder().destroyTime(3.0f) + public static final Block CHERRY_DOOR = register(new DoorBlock("cherry_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block DARK_OAK_DOOR = register(new Block("dark_oak_door", builder().destroyTime(3.0f) + public static final Block DARK_OAK_DOOR = register(new DoorBlock("dark_oak_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block MANGROVE_DOOR = register(new Block("mangrove_door", builder().destroyTime(3.0f) + public static final Block MANGROVE_DOOR = register(new DoorBlock("mangrove_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block BAMBOO_DOOR = register(new Block("bamboo_door", builder().destroyTime(3.0f) + public static final Block BAMBOO_DOOR = register(new DoorBlock("bamboo_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") @@ -1548,14 +1548,14 @@ public final class Blocks { .booleanState(POWERED))); public static final Block END_ROD = register(new Block("end_rod", builder() .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block CHORUS_PLANT = register(new Block("chorus_plant", builder().destroyTime(0.4f) + public static final Block CHORUS_PLANT = register(new Block("chorus_plant", builder().destroyTime(0.4f).pushReaction(PistonBehavior.DESTROY) .booleanState(DOWN) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) .booleanState(UP) .booleanState(WEST))); - public static final Block CHORUS_FLOWER = register(new Block("chorus_flower", builder().destroyTime(0.4f) + public static final Block CHORUS_FLOWER = register(new Block("chorus_flower", builder().destroyTime(0.4f).pushReaction(PistonBehavior.DESTROY) .intState(AGE_5, 0, 5))); public static final Block PURPUR_BLOCK = register(new Block("purpur_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); public static final Block PURPUR_PILLAR = register(new Block("purpur_pillar", builder().requiresCorrectToolForDrops().destroyTime(1.5f) @@ -1566,17 +1566,17 @@ public final class Blocks { .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); public static final Block END_STONE_BRICKS = register(new Block("end_stone_bricks", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); - public static final Block TORCHFLOWER_CROP = register(new Block("torchflower_crop", builder() + public static final Block TORCHFLOWER_CROP = register(new Block("torchflower_crop", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_1, 0, 1))); - public static final Block PITCHER_CROP = register(new Block("pitcher_crop", builder() + public static final Block PITCHER_CROP = register(new Block("pitcher_crop", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_4, 0, 4) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); - public static final Block PITCHER_PLANT = register(new Block("pitcher_plant", builder() + public static final Block PITCHER_PLANT = register(new Block("pitcher_plant", builder().pushReaction(PistonBehavior.DESTROY) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); - public static final Block BEETROOTS = register(new Block("beetroots", builder() + public static final Block BEETROOTS = register(new Block("beetroots", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_3, 0, 3))); public static final Block DIRT_PATH = register(new Block("dirt_path", builder().destroyTime(0.65f))); - public static final Block END_GATEWAY = register(new Block("end_gateway", builder().setBlockEntity().destroyTime(-1.0f))); + public static final Block END_GATEWAY = register(new Block("end_gateway", builder().setBlockEntity().destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK))); public static final Block REPEATING_COMMAND_BLOCK = register(new Block("repeating_command_block", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(-1.0f) .booleanState(CONDITIONAL) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); @@ -1590,75 +1590,75 @@ public final class Blocks { public static final Block RED_NETHER_BRICKS = register(new Block("red_nether_bricks", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); public static final Block BONE_BLOCK = register(new Block("bone_block", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); - public static final Block STRUCTURE_VOID = register(new Block("structure_void", builder())); + public static final Block STRUCTURE_VOID = register(new Block("structure_void", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block OBSERVER = register(new Block("observer", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .booleanState(POWERED))); - public static final Block SHULKER_BOX = register(new Block("shulker_box", builder().setBlockEntity().destroyTime(2.0f) + public static final Block SHULKER_BOX = register(new Block("shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block WHITE_SHULKER_BOX = register(new Block("white_shulker_box", builder().setBlockEntity().destroyTime(2.0f) + public static final Block WHITE_SHULKER_BOX = register(new Block("white_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block ORANGE_SHULKER_BOX = register(new Block("orange_shulker_box", builder().setBlockEntity().destroyTime(2.0f) + public static final Block ORANGE_SHULKER_BOX = register(new Block("orange_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block MAGENTA_SHULKER_BOX = register(new Block("magenta_shulker_box", builder().setBlockEntity().destroyTime(2.0f) + public static final Block MAGENTA_SHULKER_BOX = register(new Block("magenta_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block LIGHT_BLUE_SHULKER_BOX = register(new Block("light_blue_shulker_box", builder().setBlockEntity().destroyTime(2.0f) + public static final Block LIGHT_BLUE_SHULKER_BOX = register(new Block("light_blue_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block YELLOW_SHULKER_BOX = register(new Block("yellow_shulker_box", builder().setBlockEntity().destroyTime(2.0f) + public static final Block YELLOW_SHULKER_BOX = register(new Block("yellow_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block LIME_SHULKER_BOX = register(new Block("lime_shulker_box", builder().setBlockEntity().destroyTime(2.0f) + public static final Block LIME_SHULKER_BOX = register(new Block("lime_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block PINK_SHULKER_BOX = register(new Block("pink_shulker_box", builder().setBlockEntity().destroyTime(2.0f) + public static final Block PINK_SHULKER_BOX = register(new Block("pink_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block GRAY_SHULKER_BOX = register(new Block("gray_shulker_box", builder().setBlockEntity().destroyTime(2.0f) + public static final Block GRAY_SHULKER_BOX = register(new Block("gray_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block LIGHT_GRAY_SHULKER_BOX = register(new Block("light_gray_shulker_box", builder().setBlockEntity().destroyTime(2.0f) + public static final Block LIGHT_GRAY_SHULKER_BOX = register(new Block("light_gray_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block CYAN_SHULKER_BOX = register(new Block("cyan_shulker_box", builder().setBlockEntity().destroyTime(2.0f) + public static final Block CYAN_SHULKER_BOX = register(new Block("cyan_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block PURPLE_SHULKER_BOX = register(new Block("purple_shulker_box", builder().setBlockEntity().destroyTime(2.0f) + public static final Block PURPLE_SHULKER_BOX = register(new Block("purple_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block BLUE_SHULKER_BOX = register(new Block("blue_shulker_box", builder().setBlockEntity().destroyTime(2.0f) + public static final Block BLUE_SHULKER_BOX = register(new Block("blue_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block BROWN_SHULKER_BOX = register(new Block("brown_shulker_box", builder().setBlockEntity().destroyTime(2.0f) + public static final Block BROWN_SHULKER_BOX = register(new Block("brown_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block GREEN_SHULKER_BOX = register(new Block("green_shulker_box", builder().setBlockEntity().destroyTime(2.0f) + public static final Block GREEN_SHULKER_BOX = register(new Block("green_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block RED_SHULKER_BOX = register(new Block("red_shulker_box", builder().setBlockEntity().destroyTime(2.0f) + public static final Block RED_SHULKER_BOX = register(new Block("red_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block BLACK_SHULKER_BOX = register(new Block("black_shulker_box", builder().setBlockEntity().destroyTime(2.0f) + public static final Block BLACK_SHULKER_BOX = register(new Block("black_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block WHITE_GLAZED_TERRACOTTA = register(new Block("white_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) + public static final Block WHITE_GLAZED_TERRACOTTA = register(new Block("white_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block ORANGE_GLAZED_TERRACOTTA = register(new Block("orange_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) + public static final Block ORANGE_GLAZED_TERRACOTTA = register(new Block("orange_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block MAGENTA_GLAZED_TERRACOTTA = register(new Block("magenta_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) + public static final Block MAGENTA_GLAZED_TERRACOTTA = register(new Block("magenta_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block LIGHT_BLUE_GLAZED_TERRACOTTA = register(new Block("light_blue_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) + public static final Block LIGHT_BLUE_GLAZED_TERRACOTTA = register(new Block("light_blue_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block YELLOW_GLAZED_TERRACOTTA = register(new Block("yellow_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) + public static final Block YELLOW_GLAZED_TERRACOTTA = register(new Block("yellow_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block LIME_GLAZED_TERRACOTTA = register(new Block("lime_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) + public static final Block LIME_GLAZED_TERRACOTTA = register(new Block("lime_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block PINK_GLAZED_TERRACOTTA = register(new Block("pink_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) + public static final Block PINK_GLAZED_TERRACOTTA = register(new Block("pink_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block GRAY_GLAZED_TERRACOTTA = register(new Block("gray_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) + public static final Block GRAY_GLAZED_TERRACOTTA = register(new Block("gray_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block LIGHT_GRAY_GLAZED_TERRACOTTA = register(new Block("light_gray_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) + public static final Block LIGHT_GRAY_GLAZED_TERRACOTTA = register(new Block("light_gray_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block CYAN_GLAZED_TERRACOTTA = register(new Block("cyan_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) + public static final Block CYAN_GLAZED_TERRACOTTA = register(new Block("cyan_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block PURPLE_GLAZED_TERRACOTTA = register(new Block("purple_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) + public static final Block PURPLE_GLAZED_TERRACOTTA = register(new Block("purple_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block BLUE_GLAZED_TERRACOTTA = register(new Block("blue_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) + public static final Block BLUE_GLAZED_TERRACOTTA = register(new Block("blue_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block BROWN_GLAZED_TERRACOTTA = register(new Block("brown_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) + public static final Block BROWN_GLAZED_TERRACOTTA = register(new Block("brown_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block GREEN_GLAZED_TERRACOTTA = register(new Block("green_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) + public static final Block GREEN_GLAZED_TERRACOTTA = register(new Block("green_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block RED_GLAZED_TERRACOTTA = register(new Block("red_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) + public static final Block RED_GLAZED_TERRACOTTA = register(new Block("red_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block BLACK_GLAZED_TERRACOTTA = register(new Block("black_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f) + public static final Block BLACK_GLAZED_TERRACOTTA = register(new Block("black_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); public static final Block WHITE_CONCRETE = register(new Block("white_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f))); public static final Block ORANGE_CONCRETE = register(new Block("orange_concrete", builder().requiresCorrectToolForDrops().destroyTime(1.8f))); @@ -1692,11 +1692,11 @@ public final class Blocks { public static final Block GREEN_CONCRETE_POWDER = register(new Block("green_concrete_powder", builder().destroyTime(0.5f))); public static final Block RED_CONCRETE_POWDER = register(new Block("red_concrete_powder", builder().destroyTime(0.5f))); public static final Block BLACK_CONCRETE_POWDER = register(new Block("black_concrete_powder", builder().destroyTime(0.5f))); - public static final Block KELP = register(new Block("kelp", builder() + public static final Block KELP = register(new Block("kelp", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_25, 0, 25))); - public static final Block KELP_PLANT = register(new Block("kelp_plant", builder())); + public static final Block KELP_PLANT = register(new Block("kelp_plant", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block DRIED_KELP_BLOCK = register(new Block("dried_kelp_block", builder().destroyTime(0.5f))); - public static final Block TURTLE_EGG = register(new Block("turtle_egg", builder().destroyTime(0.5f) + public static final Block TURTLE_EGG = register(new Block("turtle_egg", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .intState(EGGS, 1, 4) .intState(HATCH, 0, 2))); public static final Block SNIFFER_EGG = register(new Block("sniffer_egg", builder().destroyTime(0.5f) @@ -1721,15 +1721,15 @@ public final class Blocks { .booleanState(WATERLOGGED))); public static final Block DEAD_HORN_CORAL = register(new Block("dead_horn_coral", builder().requiresCorrectToolForDrops() .booleanState(WATERLOGGED))); - public static final Block TUBE_CORAL = register(new Block("tube_coral", builder() + public static final Block TUBE_CORAL = register(new Block("tube_coral", builder().pushReaction(PistonBehavior.DESTROY) .booleanState(WATERLOGGED))); - public static final Block BRAIN_CORAL = register(new Block("brain_coral", builder() + public static final Block BRAIN_CORAL = register(new Block("brain_coral", builder().pushReaction(PistonBehavior.DESTROY) .booleanState(WATERLOGGED))); - public static final Block BUBBLE_CORAL = register(new Block("bubble_coral", builder() + public static final Block BUBBLE_CORAL = register(new Block("bubble_coral", builder().pushReaction(PistonBehavior.DESTROY) .booleanState(WATERLOGGED))); - public static final Block FIRE_CORAL = register(new Block("fire_coral", builder() + public static final Block FIRE_CORAL = register(new Block("fire_coral", builder().pushReaction(PistonBehavior.DESTROY) .booleanState(WATERLOGGED))); - public static final Block HORN_CORAL = register(new Block("horn_coral", builder() + public static final Block HORN_CORAL = register(new Block("horn_coral", builder().pushReaction(PistonBehavior.DESTROY) .booleanState(WATERLOGGED))); public static final Block DEAD_TUBE_CORAL_FAN = register(new Block("dead_tube_coral_fan", builder().requiresCorrectToolForDrops() .booleanState(WATERLOGGED))); @@ -1741,15 +1741,15 @@ public final class Blocks { .booleanState(WATERLOGGED))); public static final Block DEAD_HORN_CORAL_FAN = register(new Block("dead_horn_coral_fan", builder().requiresCorrectToolForDrops() .booleanState(WATERLOGGED))); - public static final Block TUBE_CORAL_FAN = register(new Block("tube_coral_fan", builder() + public static final Block TUBE_CORAL_FAN = register(new Block("tube_coral_fan", builder().pushReaction(PistonBehavior.DESTROY) .booleanState(WATERLOGGED))); - public static final Block BRAIN_CORAL_FAN = register(new Block("brain_coral_fan", builder() + public static final Block BRAIN_CORAL_FAN = register(new Block("brain_coral_fan", builder().pushReaction(PistonBehavior.DESTROY) .booleanState(WATERLOGGED))); - public static final Block BUBBLE_CORAL_FAN = register(new Block("bubble_coral_fan", builder() + public static final Block BUBBLE_CORAL_FAN = register(new Block("bubble_coral_fan", builder().pushReaction(PistonBehavior.DESTROY) .booleanState(WATERLOGGED))); - public static final Block FIRE_CORAL_FAN = register(new Block("fire_coral_fan", builder() + public static final Block FIRE_CORAL_FAN = register(new Block("fire_coral_fan", builder().pushReaction(PistonBehavior.DESTROY) .booleanState(WATERLOGGED))); - public static final Block HORN_CORAL_FAN = register(new Block("horn_coral_fan", builder() + public static final Block HORN_CORAL_FAN = register(new Block("horn_coral_fan", builder().pushReaction(PistonBehavior.DESTROY) .booleanState(WATERLOGGED))); public static final Block DEAD_TUBE_CORAL_WALL_FAN = register(new Block("dead_tube_coral_wall_fan", builder().requiresCorrectToolForDrops() .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) @@ -1766,36 +1766,36 @@ public final class Blocks { public static final Block DEAD_HORN_CORAL_WALL_FAN = register(new Block("dead_horn_coral_wall_fan", builder().requiresCorrectToolForDrops() .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block TUBE_CORAL_WALL_FAN = register(new Block("tube_coral_wall_fan", builder() + public static final Block TUBE_CORAL_WALL_FAN = register(new Block("tube_coral_wall_fan", builder().pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block BRAIN_CORAL_WALL_FAN = register(new Block("brain_coral_wall_fan", builder() + public static final Block BRAIN_CORAL_WALL_FAN = register(new Block("brain_coral_wall_fan", builder().pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block BUBBLE_CORAL_WALL_FAN = register(new Block("bubble_coral_wall_fan", builder() + public static final Block BUBBLE_CORAL_WALL_FAN = register(new Block("bubble_coral_wall_fan", builder().pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block FIRE_CORAL_WALL_FAN = register(new Block("fire_coral_wall_fan", builder() + public static final Block FIRE_CORAL_WALL_FAN = register(new Block("fire_coral_wall_fan", builder().pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block HORN_CORAL_WALL_FAN = register(new Block("horn_coral_wall_fan", builder() + public static final Block HORN_CORAL_WALL_FAN = register(new Block("horn_coral_wall_fan", builder().pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block SEA_PICKLE = register(new Block("sea_pickle", builder() + public static final Block SEA_PICKLE = register(new Block("sea_pickle", builder().pushReaction(PistonBehavior.DESTROY) .intState(PICKLES, 1, 4) .booleanState(WATERLOGGED))); public static final Block BLUE_ICE = register(new Block("blue_ice", builder().destroyTime(2.8f))); public static final Block CONDUIT = register(new Block("conduit", builder().setBlockEntity().destroyTime(3.0f) .booleanState(WATERLOGGED))); - public static final Block BAMBOO_SAPLING = register(new Block("bamboo_sapling", builder().destroyTime(1.0f))); - public static final Block BAMBOO = register(new Block("bamboo", builder().destroyTime(1.0f) + public static final Block BAMBOO_SAPLING = register(new Block("bamboo_sapling", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY))); + public static final Block BAMBOO = register(new Block("bamboo", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .intState(AGE_1, 0, 1) .enumState(BAMBOO_LEAVES, "none", "small", "large") .intState(STAGE, 0, 1))); - public static final Block POTTED_BAMBOO = register(new Block("potted_bamboo", builder())); + public static final Block POTTED_BAMBOO = register(new FlowerPotBlock("potted_bamboo", BAMBOO, builder().pushReaction(PistonBehavior.DESTROY))); public static final Block VOID_AIR = register(new Block("void_air", builder())); public static final Block CAVE_AIR = register(new Block("cave_air", builder())); - public static final Block BUBBLE_COLUMN = register(new Block("bubble_column", builder() + public static final Block BUBBLE_COLUMN = register(new Block("bubble_column", builder().pushReaction(PistonBehavior.DESTROY) .booleanState(DRAG))); public static final Block POLISHED_GRANITE_STAIRS = register(new Block("polished_granite_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) @@ -1997,7 +1997,7 @@ public final class Blocks { .booleanState(UP) .booleanState(WATERLOGGED) .enumState(WEST_WALL, "none", "low", "tall"))); - public static final Block SCAFFOLDING = register(new Block("scaffolding", builder() + public static final Block SCAFFOLDING = register(new Block("scaffolding", builder().pushReaction(PistonBehavior.DESTROY) .booleanState(BOTTOM) .intState(STABILITY_DISTANCE, 0, 7) .booleanState(WATERLOGGED))); @@ -2014,24 +2014,24 @@ public final class Blocks { .booleanState(LIT))); public static final Block CARTOGRAPHY_TABLE = register(new Block("cartography_table", builder().destroyTime(2.5f))); public static final Block FLETCHING_TABLE = register(new Block("fletching_table", builder().destroyTime(2.5f))); - public static final Block GRINDSTONE = register(new Block("grindstone", builder().requiresCorrectToolForDrops().destroyTime(2.0f) + public static final Block GRINDSTONE = register(new Block("grindstone", builder().requiresCorrectToolForDrops().destroyTime(2.0f).pushReaction(PistonBehavior.BLOCK) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block LECTERN = register(new Block("lectern", builder().setBlockEntity().destroyTime(2.5f) + public static final Block LECTERN = register(new LecternBlock("lectern", builder().setBlockEntity().destroyTime(2.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(HAS_BOOK) .booleanState(POWERED))); public static final Block SMITHING_TABLE = register(new Block("smithing_table", builder().destroyTime(2.5f))); public static final Block STONECUTTER = register(new Block("stonecutter", builder().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block BELL = register(new Block("bell", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(5.0f) + public static final Block BELL = register(new Block("bell", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(5.0f).pushReaction(PistonBehavior.DESTROY) .enumState(BELL_ATTACHMENT, "floor", "ceiling", "single_wall", "double_wall") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block LANTERN = register(new Block("lantern", builder().requiresCorrectToolForDrops().destroyTime(3.5f) + public static final Block LANTERN = register(new Block("lantern", builder().requiresCorrectToolForDrops().destroyTime(3.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(HANGING) .booleanState(WATERLOGGED))); - public static final Block SOUL_LANTERN = register(new Block("soul_lantern", builder().requiresCorrectToolForDrops().destroyTime(3.5f) + public static final Block SOUL_LANTERN = register(new Block("soul_lantern", builder().requiresCorrectToolForDrops().destroyTime(3.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(HANGING) .booleanState(WATERLOGGED))); public static final Block CAMPFIRE = register(new Block("campfire", builder().setBlockEntity().destroyTime(2.0f) @@ -2044,7 +2044,7 @@ public final class Blocks { .booleanState(LIT) .booleanState(SIGNAL_FIRE) .booleanState(WATERLOGGED))); - public static final Block SWEET_BERRY_BUSH = register(new Block("sweet_berry_bush", builder() + public static final Block SWEET_BERRY_BUSH = register(new Block("sweet_berry_bush", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_3, 0, 3))); public static final Block WARPED_STEM = register(new Block("warped_stem", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); @@ -2055,10 +2055,10 @@ public final class Blocks { public static final Block STRIPPED_WARPED_HYPHAE = register(new Block("stripped_warped_hyphae", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); public static final Block WARPED_NYLIUM = register(new Block("warped_nylium", builder().requiresCorrectToolForDrops().destroyTime(0.4f))); - public static final Block WARPED_FUNGUS = register(new Block("warped_fungus", builder())); + public static final Block WARPED_FUNGUS = register(new Block("warped_fungus", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block WARPED_WART_BLOCK = register(new Block("warped_wart_block", builder().destroyTime(1.0f))); - public static final Block WARPED_ROOTS = register(new Block("warped_roots", builder())); - public static final Block NETHER_SPROUTS = register(new Block("nether_sprouts", builder())); + public static final Block WARPED_ROOTS = register(new Block("warped_roots", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block NETHER_SPROUTS = register(new Block("nether_sprouts", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block CRIMSON_STEM = register(new Block("crimson_stem", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); public static final Block STRIPPED_CRIMSON_STEM = register(new Block("stripped_crimson_stem", builder().destroyTime(2.0f) @@ -2068,15 +2068,15 @@ public final class Blocks { public static final Block STRIPPED_CRIMSON_HYPHAE = register(new Block("stripped_crimson_hyphae", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); public static final Block CRIMSON_NYLIUM = register(new Block("crimson_nylium", builder().requiresCorrectToolForDrops().destroyTime(0.4f))); - public static final Block CRIMSON_FUNGUS = register(new Block("crimson_fungus", builder())); + public static final Block CRIMSON_FUNGUS = register(new Block("crimson_fungus", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block SHROOMLIGHT = register(new Block("shroomlight", builder().destroyTime(1.0f))); - public static final Block WEEPING_VINES = register(new Block("weeping_vines", builder() + public static final Block WEEPING_VINES = register(new Block("weeping_vines", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_25, 0, 25))); - public static final Block WEEPING_VINES_PLANT = register(new Block("weeping_vines_plant", builder())); - public static final Block TWISTING_VINES = register(new Block("twisting_vines", builder() + public static final Block WEEPING_VINES_PLANT = register(new Block("weeping_vines_plant", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block TWISTING_VINES = register(new Block("twisting_vines", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_25, 0, 25))); - public static final Block TWISTING_VINES_PLANT = register(new Block("twisting_vines_plant", builder())); - public static final Block CRIMSON_ROOTS = register(new Block("crimson_roots", builder())); + public static final Block TWISTING_VINES_PLANT = register(new Block("twisting_vines_plant", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block CRIMSON_ROOTS = register(new Block("crimson_roots", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block CRIMSON_PLANKS = register(new Block("crimson_planks", builder().destroyTime(2.0f))); public static final Block WARPED_PLANKS = register(new Block("warped_planks", builder().destroyTime(2.0f))); public static final Block CRIMSON_SLAB = register(new Block("crimson_slab", builder().destroyTime(2.0f) @@ -2085,9 +2085,9 @@ public final class Blocks { public static final Block WARPED_SLAB = register(new Block("warped_slab", builder().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block CRIMSON_PRESSURE_PLATE = register(new Block("crimson_pressure_plate", builder().destroyTime(0.5f) + public static final Block CRIMSON_PRESSURE_PLATE = register(new Block("crimson_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED))); - public static final Block WARPED_PRESSURE_PLATE = register(new Block("warped_pressure_plate", builder().destroyTime(0.5f) + public static final Block WARPED_PRESSURE_PLATE = register(new Block("warped_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED))); public static final Block CRIMSON_FENCE = register(new Block("crimson_fence", builder().destroyTime(2.0f) .booleanState(EAST) @@ -2133,21 +2133,21 @@ public final class Blocks { .enumState(HALF, "top", "bottom") .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") .booleanState(WATERLOGGED))); - public static final Block CRIMSON_BUTTON = register(new Block("crimson_button", builder().destroyTime(0.5f) + public static final Block CRIMSON_BUTTON = register(new Block("crimson_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block WARPED_BUTTON = register(new Block("warped_button", builder().destroyTime(0.5f) + public static final Block WARPED_BUTTON = register(new Block("warped_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block CRIMSON_DOOR = register(new Block("crimson_door", builder().destroyTime(3.0f) + public static final Block CRIMSON_DOOR = register(new DoorBlock("crimson_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block WARPED_DOOR = register(new Block("warped_door", builder().destroyTime(3.0f) + public static final Block WARPED_DOOR = register(new DoorBlock("warped_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") @@ -2186,11 +2186,11 @@ public final class Blocks { public static final Block CRYING_OBSIDIAN = register(new Block("crying_obsidian", builder().requiresCorrectToolForDrops().destroyTime(50.0f))); public static final Block RESPAWN_ANCHOR = register(new Block("respawn_anchor", builder().requiresCorrectToolForDrops().destroyTime(50.0f) .intState(RESPAWN_ANCHOR_CHARGES, 0, 4))); - public static final Block POTTED_CRIMSON_FUNGUS = register(new Block("potted_crimson_fungus", builder())); - public static final Block POTTED_WARPED_FUNGUS = register(new Block("potted_warped_fungus", builder())); - public static final Block POTTED_CRIMSON_ROOTS = register(new Block("potted_crimson_roots", builder())); - public static final Block POTTED_WARPED_ROOTS = register(new Block("potted_warped_roots", builder())); - public static final Block LODESTONE = register(new Block("lodestone", builder().requiresCorrectToolForDrops().destroyTime(3.5f))); + public static final Block POTTED_CRIMSON_FUNGUS = register(new FlowerPotBlock("potted_crimson_fungus", CRIMSON_FUNGUS, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_WARPED_FUNGUS = register(new FlowerPotBlock("potted_warped_fungus", WARPED_FUNGUS, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_CRIMSON_ROOTS = register(new FlowerPotBlock("potted_crimson_roots", CRIMSON_ROOTS, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_WARPED_ROOTS = register(new FlowerPotBlock("potted_warped_roots", WARPED_ROOTS, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block LODESTONE = register(new Block("lodestone", builder().requiresCorrectToolForDrops().destroyTime(3.5f).pushReaction(PistonBehavior.BLOCK))); public static final Block BLACKSTONE = register(new Block("blackstone", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); public static final Block BLACKSTONE_STAIRS = register(new Block("blackstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) @@ -2235,9 +2235,9 @@ public final class Blocks { public static final Block POLISHED_BLACKSTONE_SLAB = register(new Block("polished_blackstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block POLISHED_BLACKSTONE_PRESSURE_PLATE = register(new Block("polished_blackstone_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f) + public static final Block POLISHED_BLACKSTONE_PRESSURE_PLATE = register(new Block("polished_blackstone_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED))); - public static final Block POLISHED_BLACKSTONE_BUTTON = register(new Block("polished_blackstone_button", builder().destroyTime(0.5f) + public static final Block POLISHED_BLACKSTONE_BUTTON = register(new Block("polished_blackstone_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); @@ -2251,120 +2251,120 @@ public final class Blocks { public static final Block CHISELED_NETHER_BRICKS = register(new Block("chiseled_nether_bricks", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); public static final Block CRACKED_NETHER_BRICKS = register(new Block("cracked_nether_bricks", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); public static final Block QUARTZ_BRICKS = register(new Block("quartz_bricks", builder().requiresCorrectToolForDrops().destroyTime(0.8f))); - public static final Block CANDLE = register(new Block("candle", builder().destroyTime(0.1f) + public static final Block CANDLE = register(new Block("candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block WHITE_CANDLE = register(new Block("white_candle", builder().destroyTime(0.1f) + public static final Block WHITE_CANDLE = register(new Block("white_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block ORANGE_CANDLE = register(new Block("orange_candle", builder().destroyTime(0.1f) + public static final Block ORANGE_CANDLE = register(new Block("orange_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block MAGENTA_CANDLE = register(new Block("magenta_candle", builder().destroyTime(0.1f) + public static final Block MAGENTA_CANDLE = register(new Block("magenta_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block LIGHT_BLUE_CANDLE = register(new Block("light_blue_candle", builder().destroyTime(0.1f) + public static final Block LIGHT_BLUE_CANDLE = register(new Block("light_blue_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block YELLOW_CANDLE = register(new Block("yellow_candle", builder().destroyTime(0.1f) + public static final Block YELLOW_CANDLE = register(new Block("yellow_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block LIME_CANDLE = register(new Block("lime_candle", builder().destroyTime(0.1f) + public static final Block LIME_CANDLE = register(new Block("lime_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block PINK_CANDLE = register(new Block("pink_candle", builder().destroyTime(0.1f) + public static final Block PINK_CANDLE = register(new Block("pink_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block GRAY_CANDLE = register(new Block("gray_candle", builder().destroyTime(0.1f) + public static final Block GRAY_CANDLE = register(new Block("gray_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block LIGHT_GRAY_CANDLE = register(new Block("light_gray_candle", builder().destroyTime(0.1f) + public static final Block LIGHT_GRAY_CANDLE = register(new Block("light_gray_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block CYAN_CANDLE = register(new Block("cyan_candle", builder().destroyTime(0.1f) + public static final Block CYAN_CANDLE = register(new Block("cyan_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block PURPLE_CANDLE = register(new Block("purple_candle", builder().destroyTime(0.1f) + public static final Block PURPLE_CANDLE = register(new Block("purple_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block BLUE_CANDLE = register(new Block("blue_candle", builder().destroyTime(0.1f) + public static final Block BLUE_CANDLE = register(new Block("blue_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block BROWN_CANDLE = register(new Block("brown_candle", builder().destroyTime(0.1f) + public static final Block BROWN_CANDLE = register(new Block("brown_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block GREEN_CANDLE = register(new Block("green_candle", builder().destroyTime(0.1f) + public static final Block GREEN_CANDLE = register(new Block("green_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block RED_CANDLE = register(new Block("red_candle", builder().destroyTime(0.1f) + public static final Block RED_CANDLE = register(new Block("red_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block BLACK_CANDLE = register(new Block("black_candle", builder().destroyTime(0.1f) + public static final Block BLACK_CANDLE = register(new Block("black_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block CANDLE_CAKE = register(new Block("candle_cake", builder().destroyTime(0.5f) + public static final Block CANDLE_CAKE = register(new Block("candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(LIT))); - public static final Block WHITE_CANDLE_CAKE = register(new Block("white_candle_cake", builder().destroyTime(0.5f) + public static final Block WHITE_CANDLE_CAKE = register(new Block("white_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(LIT))); - public static final Block ORANGE_CANDLE_CAKE = register(new Block("orange_candle_cake", builder().destroyTime(0.5f) + public static final Block ORANGE_CANDLE_CAKE = register(new Block("orange_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(LIT))); - public static final Block MAGENTA_CANDLE_CAKE = register(new Block("magenta_candle_cake", builder().destroyTime(0.5f) + public static final Block MAGENTA_CANDLE_CAKE = register(new Block("magenta_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(LIT))); - public static final Block LIGHT_BLUE_CANDLE_CAKE = register(new Block("light_blue_candle_cake", builder().destroyTime(0.5f) + public static final Block LIGHT_BLUE_CANDLE_CAKE = register(new Block("light_blue_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(LIT))); - public static final Block YELLOW_CANDLE_CAKE = register(new Block("yellow_candle_cake", builder().destroyTime(0.5f) + public static final Block YELLOW_CANDLE_CAKE = register(new Block("yellow_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(LIT))); - public static final Block LIME_CANDLE_CAKE = register(new Block("lime_candle_cake", builder().destroyTime(0.5f) + public static final Block LIME_CANDLE_CAKE = register(new Block("lime_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(LIT))); - public static final Block PINK_CANDLE_CAKE = register(new Block("pink_candle_cake", builder().destroyTime(0.5f) + public static final Block PINK_CANDLE_CAKE = register(new Block("pink_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(LIT))); - public static final Block GRAY_CANDLE_CAKE = register(new Block("gray_candle_cake", builder().destroyTime(0.5f) + public static final Block GRAY_CANDLE_CAKE = register(new Block("gray_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(LIT))); - public static final Block LIGHT_GRAY_CANDLE_CAKE = register(new Block("light_gray_candle_cake", builder().destroyTime(0.5f) + public static final Block LIGHT_GRAY_CANDLE_CAKE = register(new Block("light_gray_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(LIT))); - public static final Block CYAN_CANDLE_CAKE = register(new Block("cyan_candle_cake", builder().destroyTime(0.5f) + public static final Block CYAN_CANDLE_CAKE = register(new Block("cyan_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(LIT))); - public static final Block PURPLE_CANDLE_CAKE = register(new Block("purple_candle_cake", builder().destroyTime(0.5f) + public static final Block PURPLE_CANDLE_CAKE = register(new Block("purple_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(LIT))); - public static final Block BLUE_CANDLE_CAKE = register(new Block("blue_candle_cake", builder().destroyTime(0.5f) + public static final Block BLUE_CANDLE_CAKE = register(new Block("blue_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(LIT))); - public static final Block BROWN_CANDLE_CAKE = register(new Block("brown_candle_cake", builder().destroyTime(0.5f) + public static final Block BROWN_CANDLE_CAKE = register(new Block("brown_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(LIT))); - public static final Block GREEN_CANDLE_CAKE = register(new Block("green_candle_cake", builder().destroyTime(0.5f) + public static final Block GREEN_CANDLE_CAKE = register(new Block("green_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(LIT))); - public static final Block RED_CANDLE_CAKE = register(new Block("red_candle_cake", builder().destroyTime(0.5f) + public static final Block RED_CANDLE_CAKE = register(new Block("red_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(LIT))); - public static final Block BLACK_CANDLE_CAKE = register(new Block("black_candle_cake", builder().destroyTime(0.5f) + public static final Block BLACK_CANDLE_CAKE = register(new Block("black_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(LIT))); public static final Block AMETHYST_BLOCK = register(new Block("amethyst_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); - public static final Block BUDDING_AMETHYST = register(new Block("budding_amethyst", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); - public static final Block AMETHYST_CLUSTER = register(new Block("amethyst_cluster", builder().destroyTime(1.5f) + public static final Block BUDDING_AMETHYST = register(new Block("budding_amethyst", builder().requiresCorrectToolForDrops().destroyTime(1.5f).pushReaction(PistonBehavior.DESTROY))); + public static final Block AMETHYST_CLUSTER = register(new Block("amethyst_cluster", builder().destroyTime(1.5f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .booleanState(WATERLOGGED))); - public static final Block LARGE_AMETHYST_BUD = register(new Block("large_amethyst_bud", builder().destroyTime(1.5f) + public static final Block LARGE_AMETHYST_BUD = register(new Block("large_amethyst_bud", builder().destroyTime(1.5f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .booleanState(WATERLOGGED))); - public static final Block MEDIUM_AMETHYST_BUD = register(new Block("medium_amethyst_bud", builder().destroyTime(1.5f) + public static final Block MEDIUM_AMETHYST_BUD = register(new Block("medium_amethyst_bud", builder().destroyTime(1.5f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .booleanState(WATERLOGGED))); - public static final Block SMALL_AMETHYST_BUD = register(new Block("small_amethyst_bud", builder().destroyTime(1.5f) + public static final Block SMALL_AMETHYST_BUD = register(new Block("small_amethyst_bud", builder().destroyTime(1.5f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .booleanState(WATERLOGGED))); public static final Block TUFF = register(new Block("tuff", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); @@ -2430,7 +2430,7 @@ public final class Blocks { .enumState(SCULK_SENSOR_PHASE, "inactive", "active", "cooldown") .booleanState(WATERLOGGED))); public static final Block SCULK = register(new Block("sculk", builder().destroyTime(0.2f))); - public static final Block SCULK_VEIN = register(new Block("sculk_vein", builder().destroyTime(0.2f) + public static final Block SCULK_VEIN = register(new Block("sculk_vein", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .booleanState(DOWN) .booleanState(EAST) .booleanState(NORTH) @@ -2534,49 +2534,49 @@ public final class Blocks { public static final Block WAXED_CUT_COPPER_SLAB = register(new Block("waxed_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(SLAB_TYPE, "top", "bottom", "double") .booleanState(WATERLOGGED))); - public static final Block COPPER_DOOR = register(new Block("copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f) + public static final Block COPPER_DOOR = register(new DoorBlock("copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block EXPOSED_COPPER_DOOR = register(new Block("exposed_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f) + public static final Block EXPOSED_COPPER_DOOR = register(new DoorBlock("exposed_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block OXIDIZED_COPPER_DOOR = register(new Block("oxidized_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f) + public static final Block OXIDIZED_COPPER_DOOR = register(new DoorBlock("oxidized_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block WEATHERED_COPPER_DOOR = register(new Block("weathered_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f) + public static final Block WEATHERED_COPPER_DOOR = register(new DoorBlock("weathered_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block WAXED_COPPER_DOOR = register(new Block("waxed_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f) + public static final Block WAXED_COPPER_DOOR = register(new DoorBlock("waxed_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block WAXED_EXPOSED_COPPER_DOOR = register(new Block("waxed_exposed_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f) + public static final Block WAXED_EXPOSED_COPPER_DOOR = register(new DoorBlock("waxed_exposed_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block WAXED_OXIDIZED_COPPER_DOOR = register(new Block("waxed_oxidized_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f) + public static final Block WAXED_OXIDIZED_COPPER_DOOR = register(new DoorBlock("waxed_oxidized_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block WAXED_WEATHERED_COPPER_DOOR = register(new Block("waxed_weathered_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f) + public static final Block WAXED_WEATHERED_COPPER_DOOR = register(new DoorBlock("waxed_weathered_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .enumState(DOOR_HINGE, "left", "right") @@ -2674,36 +2674,36 @@ public final class Blocks { .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block POINTED_DRIPSTONE = register(new Block("pointed_dripstone", builder().destroyTime(1.5f) + public static final Block POINTED_DRIPSTONE = register(new Block("pointed_dripstone", builder().destroyTime(1.5f).pushReaction(PistonBehavior.DESTROY) .enumState(DRIPSTONE_THICKNESS, "tip_merge", "tip", "frustum", "middle", "base") .enumState(VERTICAL_DIRECTION, Direction.UP, Direction.DOWN) .booleanState(WATERLOGGED))); public static final Block DRIPSTONE_BLOCK = register(new Block("dripstone_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); - public static final Block CAVE_VINES = register(new Block("cave_vines", builder() + public static final Block CAVE_VINES = register(new Block("cave_vines", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_25, 0, 25) .booleanState(BERRIES))); - public static final Block CAVE_VINES_PLANT = register(new Block("cave_vines_plant", builder() + public static final Block CAVE_VINES_PLANT = register(new Block("cave_vines_plant", builder().pushReaction(PistonBehavior.DESTROY) .booleanState(BERRIES))); - public static final Block SPORE_BLOSSOM = register(new Block("spore_blossom", builder())); - public static final Block AZALEA = register(new Block("azalea", builder())); - public static final Block FLOWERING_AZALEA = register(new Block("flowering_azalea", builder())); - public static final Block MOSS_CARPET = register(new Block("moss_carpet", builder().destroyTime(0.1f))); - public static final Block PINK_PETALS = register(new Block("pink_petals", builder() + public static final Block SPORE_BLOSSOM = register(new Block("spore_blossom", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block AZALEA = register(new Block("azalea", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block FLOWERING_AZALEA = register(new Block("flowering_azalea", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block MOSS_CARPET = register(new Block("moss_carpet", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY))); + public static final Block PINK_PETALS = register(new Block("pink_petals", builder().pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .intState(FLOWER_AMOUNT, 1, 4))); - public static final Block MOSS_BLOCK = register(new Block("moss_block", builder().destroyTime(0.1f))); - public static final Block BIG_DRIPLEAF = register(new Block("big_dripleaf", builder().destroyTime(0.1f) + public static final Block MOSS_BLOCK = register(new Block("moss_block", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY))); + public static final Block BIG_DRIPLEAF = register(new Block("big_dripleaf", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(TILT, "none", "unstable", "partial", "full") .booleanState(WATERLOGGED))); - public static final Block BIG_DRIPLEAF_STEM = register(new Block("big_dripleaf_stem", builder().destroyTime(0.1f) + public static final Block BIG_DRIPLEAF_STEM = register(new Block("big_dripleaf_stem", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block SMALL_DRIPLEAF = register(new Block("small_dripleaf", builder() + public static final Block SMALL_DRIPLEAF = register(new Block("small_dripleaf", builder().pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") .booleanState(WATERLOGGED))); - public static final Block HANGING_ROOTS = register(new Block("hanging_roots", builder() + public static final Block HANGING_ROOTS = register(new Block("hanging_roots", builder().pushReaction(PistonBehavior.DESTROY) .booleanState(WATERLOGGED))); public static final Block ROOTED_DIRT = register(new Block("rooted_dirt", builder().destroyTime(0.5f))); public static final Block MUD = register(new Block("mud", builder().destroyTime(0.5f))); @@ -2782,17 +2782,17 @@ public final class Blocks { public static final Block RAW_IRON_BLOCK = register(new Block("raw_iron_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f))); public static final Block RAW_COPPER_BLOCK = register(new Block("raw_copper_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f))); public static final Block RAW_GOLD_BLOCK = register(new Block("raw_gold_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f))); - public static final Block POTTED_AZALEA_BUSH = register(new Block("potted_azalea_bush", builder())); - public static final Block POTTED_FLOWERING_AZALEA_BUSH = register(new Block("potted_flowering_azalea_bush", builder())); + public static final Block POTTED_AZALEA_BUSH = register(new FlowerPotBlock("potted_azalea_bush", AZALEA, builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block POTTED_FLOWERING_AZALEA_BUSH = register(new FlowerPotBlock("potted_flowering_azalea_bush", FLOWERING_AZALEA, builder().pushReaction(PistonBehavior.DESTROY))); public static final Block OCHRE_FROGLIGHT = register(new Block("ochre_froglight", builder().destroyTime(0.3f) .enumState(AXIS, Axis.VALUES))); public static final Block VERDANT_FROGLIGHT = register(new Block("verdant_froglight", builder().destroyTime(0.3f) .enumState(AXIS, Axis.VALUES))); public static final Block PEARLESCENT_FROGLIGHT = register(new Block("pearlescent_froglight", builder().destroyTime(0.3f) .enumState(AXIS, Axis.VALUES))); - public static final Block FROGSPAWN = register(new Block("frogspawn", builder())); + public static final Block FROGSPAWN = register(new Block("frogspawn", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block REINFORCED_DEEPSLATE = register(new Block("reinforced_deepslate", builder().destroyTime(55.0f))); - public static final Block DECORATED_POT = register(new Block("decorated_pot", builder().setBlockEntity() + public static final Block DECORATED_POT = register(new Block("decorated_pot", builder().setBlockEntity().pushReaction(PistonBehavior.DESTROY) .booleanState(CRACKED) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java b/core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java index bbb6f8fe3..339d82f96 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java @@ -118,7 +118,7 @@ public final class Properties { public static final Property RESPAWN_ANCHOR_CHARGES = Property.create("charges"); public static final Property ROTATION_16 = Property.create("rotation"); public static final Property BED_PART = Property.create("part"); - public static final Property CHEST_TYPE = Property.create("type"); + public static final Property CHEST_TYPE = Property.create("type"); public static final Property MODE_COMPARATOR = Property.create("mode"); public static final Property DOOR_HINGE = Property.create("hinge"); public static final Property NOTEBLOCK_INSTRUMENT = Property.create("instrument"); diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java b/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java index 84822ca16..3114f31f9 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java @@ -30,8 +30,15 @@ import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap; import it.unimi.dsi.fastutil.objects.Reference2ObjectMap; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.cloudburstmc.math.vector.Vector3i; +import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; +import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; +import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.level.block.property.Property; +import org.geysermc.geyser.level.physics.PistonBehavior; import org.geysermc.geyser.registry.BlockRegistries; +import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.Identifier; import java.util.*; @@ -44,6 +51,7 @@ public class Block { private final boolean requiresCorrectToolForDrops; private final boolean hasBlockEntity; private final float destroyTime; + private final @NonNull PistonBehavior pushReaction; private int javaId = -1; public Block(String javaIdentifier, Builder builder) { @@ -51,9 +59,76 @@ public class Block { this.requiresCorrectToolForDrops = builder.requiresCorrectToolForDrops; this.hasBlockEntity = builder.hasBlockEntity; this.destroyTime = builder.destroyTime; + this.pushReaction = builder.pushReaction; builder.build(this); } + public void updateBlock(GeyserSession session, BlockState state, Vector3i position) { + BlockDefinition definition = session.getBlockMappings().getBedrockBlock(state); + sendBlockUpdatePacket(session, state, definition, position); + + { + // Extended collision boxes for custom blocks + if (!session.getBlockMappings().getExtendedCollisionBoxes().isEmpty()) { + int aboveBlock = session.getGeyser().getWorldManager().getBlockAt(session, position.getX(), position.getY() + 1, position.getZ()); + BlockDefinition aboveBedrockExtendedCollisionDefinition = session.getBlockMappings().getExtendedCollisionBoxes().get(state.javaId()); + int belowBlock = session.getGeyser().getWorldManager().getBlockAt(session, position.getX(), position.getY() - 1, position.getZ()); + BlockDefinition belowBedrockExtendedCollisionDefinition = session.getBlockMappings().getExtendedCollisionBoxes().get(belowBlock); + if (belowBedrockExtendedCollisionDefinition != null && state.is(Blocks.AIR)) { + UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); + updateBlockPacket.setDataLayer(0); + updateBlockPacket.setBlockPosition(position); + updateBlockPacket.setDefinition(belowBedrockExtendedCollisionDefinition); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); + session.sendUpstreamPacket(updateBlockPacket); + } else if (aboveBedrockExtendedCollisionDefinition != null && aboveBlock == Block.JAVA_AIR_ID) { + UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); + updateBlockPacket.setDataLayer(0); + updateBlockPacket.setBlockPosition(position.add(0, 1, 0)); + updateBlockPacket.setDefinition(aboveBedrockExtendedCollisionDefinition); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); + session.sendUpstreamPacket(updateBlockPacket); + } else if (aboveBlock == Block.JAVA_AIR_ID) { + UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); + updateBlockPacket.setDataLayer(0); + updateBlockPacket.setBlockPosition(position.add(0, 1, 0)); + updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockAir()); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); + session.sendUpstreamPacket(updateBlockPacket); + } + } + } + + handleLecternBlockUpdate(session, state, position); + } + + protected void sendBlockUpdatePacket(GeyserSession session, BlockState state, BlockDefinition definition, Vector3i position) { + UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); + updateBlockPacket.setDataLayer(0); + updateBlockPacket.setBlockPosition(position); + updateBlockPacket.setDefinition(definition); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); + session.sendUpstreamPacket(updateBlockPacket); + + UpdateBlockPacket waterPacket = new UpdateBlockPacket(); + waterPacket.setDataLayer(1); + waterPacket.setBlockPosition(position); + if (BlockRegistries.WATERLOGGED.get().get(state.javaId())) { + waterPacket.setDefinition(session.getBlockMappings().getBedrockWater()); + } else { + waterPacket.setDefinition(session.getBlockMappings().getBedrockAir()); + } + session.sendUpstreamPacket(waterPacket); + } + + protected void handleLecternBlockUpdate(GeyserSession session, BlockState state, Vector3i position) { + // Block state is out of bounds of this map - lectern has been destroyed, if it existed + if (!session.getGeyser().getWorldManager().shouldExpectLecternHandled(session)) { + session.getLecternCache().remove(position); + } + } + public String javaIdentifier() { return javaIdentifier; } @@ -70,6 +145,11 @@ public class Block { return destroyTime; } + @NonNull + public PistonBehavior pushReaction() { + return this.pushReaction; + } + public int javaId() { return javaId; } @@ -97,6 +177,7 @@ public class Block { private final Map, List>> states = new LinkedHashMap<>(); private boolean requiresCorrectToolForDrops = false; private boolean hasBlockEntity = false; + private PistonBehavior pushReaction = PistonBehavior.NORMAL; private float destroyTime; /** @@ -143,6 +224,11 @@ public class Block { return this; } + public Builder pushReaction(PistonBehavior pushReaction) { + this.pushReaction = pushReaction; + return this; + } + private void build(Block block) { if (states.isEmpty()) { BlockRegistries.BLOCK_STATES.get().add(new BlockState(block, BlockRegistries.BLOCK_STATES.get().size())); diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java index 936b711e4..23e89d99f 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java @@ -58,6 +58,10 @@ public final class BlockState { return javaId; } + public boolean is(Block block) { + return this.block == block; + } + public static BlockState of(int javaId) { return BlockRegistries.BLOCK_STATES.get(javaId); } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/CauldronBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/CauldronBlock.java new file mode 100644 index 000000000..d27969af7 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/CauldronBlock.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 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.level.block.type; + +import org.cloudburstmc.math.vector.Vector3i; +import org.cloudburstmc.nbt.NbtList; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtType; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.level.block.entity.BedrockChunkWantsBlockEntityTag; +import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator; + +public class CauldronBlock extends Block implements BedrockChunkWantsBlockEntityTag { + public CauldronBlock(String javaIdentifier, Builder builder) { + super(javaIdentifier, builder); + } + + @Override + public NbtMap createTag(GeyserSession session, Vector3i position, BlockState 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 BlockEntityTranslator.getConstantBedrockTag("Cauldron", position.getX(), position.getY(), position.getZ()) + .putByte("isMovable", (byte) 0) + .putShort("PotionId", (short) -1) + .putShort("PotionType", (short) -1) + .putList("Items", NbtType.END, NbtList.EMPTY) + .build(); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/ChestBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/ChestBlock.java new file mode 100644 index 000000000..69132ccfd --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/ChestBlock.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 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.level.block.type; + +import org.cloudburstmc.math.vector.Vector3i; +import org.cloudburstmc.nbt.NbtMapBuilder; +import org.geysermc.geyser.level.block.property.ChestType; +import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator; +import org.geysermc.geyser.util.BlockEntityUtils; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; + +public class ChestBlock extends Block { + public ChestBlock(String javaIdentifier, Builder builder) { + super(javaIdentifier, builder); + } + + @Override + public void updateBlock(GeyserSession session, BlockState state, Vector3i position) { + super.updateBlock(session, state, position); + + if (state.getValue(Properties.CHEST_TYPE) != ChestType.SINGLE) { + NbtMapBuilder tagBuilder = BlockEntityTranslator.getConstantBedrockTag(BlockEntityType.CHEST, position.getX(), position.getY(), position.getZ()); + BlockEntityUtils.getBlockEntityTranslator(BlockEntityType.CHEST).translateTag(session, tagBuilder, null, state); //TODO + BlockEntityUtils.updateBlockEntity(session, tagBuilder.build(), position); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/DoorBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/DoorBlock.java new file mode 100644 index 000000000..bfde51a79 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/DoorBlock.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 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.level.block.type; + +import org.cloudburstmc.math.vector.Vector3i; +import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.util.ChunkUtils; + +public class DoorBlock extends Block { + public DoorBlock(String javaIdentifier, Builder builder) { + super(javaIdentifier, builder); + } + + @Override + public void updateBlock(GeyserSession session, BlockState state, Vector3i position) { + super.updateBlock(session, state, position); + + if (state.getValue(Properties.DOUBLE_BLOCK_HALF).equals("upper")) { + // 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); + BlockState belowDoorBlockState = session.getGeyser().getWorldManager().blockAt(session, belowDoorPosition.getX(), belowDoorPosition.getY(), belowDoorPosition.getZ()); + ChunkUtils.updateBlock(session, belowDoorBlockState, belowDoorPosition); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/FlowerPotBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/level/block/type/FlowerPotBlock.java similarity index 60% rename from core/src/main/java/org/geysermc/geyser/translator/level/block/entity/FlowerPotBlockEntityTranslator.java rename to core/src/main/java/org/geysermc/geyser/level/block/type/FlowerPotBlock.java index 0a60b0f32..8c911ad97 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/FlowerPotBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/FlowerPotBlock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * Copyright (c) 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,65 +23,35 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.geyser.translator.level.block.entity; +package org.geysermc.geyser.level.block.type; 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.level.block.BlockStateValues; -import org.geysermc.geyser.level.block.type.BlockState; +import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.level.block.entity.BedrockChunkWantsBlockEntityTag; +import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator; import org.geysermc.geyser.util.BlockEntityUtils; -public class FlowerPotBlockEntityTranslator implements BedrockOnlyBlockEntity { - /** - * @param blockState the Java block state of a potential flower pot block - * @return true if the block is a flower pot - */ - public static boolean isFlowerBlock(int blockState) { - return BlockStateValues.getFlowerPotValues().containsKey(blockState); - } +public class FlowerPotBlock extends Block implements BedrockChunkWantsBlockEntityTag { + private final Block flower; - /** - * Get the Nukkit CompoundTag of the flower pot. - * - * @param blockState Java block state of flower pot. - * @param position Bedrock position of flower pot. - * @return Bedrock tag of flower pot. - */ - public static NbtMap getTag(GeyserSession session, int blockState, Vector3i position) { - NbtMapBuilder tagBuilder = NbtMap.builder() - .putInt("x", position.getX()) - .putInt("y", position.getY()) - .putInt("z", position.getZ()) - .putByte("isMovable", (byte) 1) - .putString("id", "FlowerPot"); - // Get the Java name of the plant inside. e.g. minecraft:oak_sapling - String name = BlockStateValues.getFlowerPotValues().get(blockState); - if (name != null) { - // Get the Bedrock CompoundTag of the block. - // This is where we need to store the *Java* name because Bedrock has six minecraft:sapling blocks with different block states. - NbtMap plant = session.getBlockMappings().getFlowerPotBlocks().get(name); - if (plant != null) { - tagBuilder.put("PlantBlock", plant.toBuilder().build()); - } - } - return tagBuilder.build(); + public FlowerPotBlock(String javaIdentifier, Block flower, Builder builder) { + super(javaIdentifier, builder); + this.flower = flower; } @Override - public boolean isBlock(int blockState) { - return isFlowerBlock(blockState); - } + public void updateBlock(GeyserSession session, BlockState state, Vector3i position) { + super.updateBlock(session, state, position); - @Override - public void updateBlock(GeyserSession session, BlockState blockState, Vector3i position) { - NbtMap tag = getTag(session, blockState.javaId(), position); + NbtMap tag = createTag(session, position, state); BlockEntityUtils.updateBlockEntity(session, tag, position); UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); updateBlockPacket.setDataLayer(0); - updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(blockState.javaId())); + updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(state)); updateBlockPacket.setBlockPosition(position); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); @@ -89,4 +59,20 @@ public class FlowerPotBlockEntityTranslator implements BedrockOnlyBlockEntity { session.sendUpstreamPacket(updateBlockPacket); BlockEntityUtils.updateBlockEntity(session, tag, position); } + + @Override + public NbtMap createTag(GeyserSession session, Vector3i position, BlockState blockState) { + NbtMapBuilder tagBuilder = BlockEntityTranslator.getConstantBedrockTag("FlowerPot", position.getX(), position.getY(), position.getZ()) + .putByte("isMovable", (byte) 1); + // Get the Java name of the plant inside. e.g. minecraft:oak_sapling + if (this.flower != Blocks.AIR) { + // Get the Bedrock CompoundTag of the block. + // This is where we need to store the *Java* name because Bedrock has six minecraft:sapling blocks with different block states. + NbtMap plant = session.getBlockMappings().getFlowerPotBlocks().get(this.flower.javaIdentifier()); + if (plant != null) { + tagBuilder.putCompound("PlantBlock", plant.toBuilder().build()); + } + } + return tagBuilder.build(); + } } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/LecternBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/LecternBlock.java new file mode 100644 index 000000000..6b8aa02b5 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/LecternBlock.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 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.level.block.type; + +import org.cloudburstmc.math.vector.Vector3i; +import org.cloudburstmc.nbt.NbtMap; +import org.geysermc.erosion.util.LecternUtils; +import org.geysermc.geyser.level.WorldManager; +import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.util.BlockEntityUtils; + +public class LecternBlock extends Block { + public LecternBlock(String javaIdentifier, Builder builder) { + super(javaIdentifier, builder); + } + + @Override + protected void handleLecternBlockUpdate(GeyserSession session, BlockState state, Vector3i position) { + WorldManager worldManager = session.getGeyser().getWorldManager(); + if (worldManager.shouldExpectLecternHandled(session)) { + worldManager.sendLecternData(session, position.getX(), position.getY(), position.getZ()); + return; + } + + boolean currentHasBook = state.getValue(Properties.HAS_BOOK); + Boolean previousHasBook = worldManager.blockAt(session, position).getValue(Properties.HAS_BOOK); // Can be null if not a lectern, watch out + if (currentHasBook != previousHasBook) { + if (currentHasBook) { + worldManager.sendLecternData(session, position.getX(), position.getY(), position.getZ()); + } else { + session.getLecternCache().remove(position); + NbtMap newLecternTag = LecternUtils.getBaseLecternTag(position.getX(), position.getY(), position.getZ(), 0).build(); + BlockEntityUtils.updateBlockEntity(session, newLecternTag, position); + } + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/MovingPistonBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/MovingPistonBlock.java new file mode 100644 index 000000000..e4df8d88b --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/MovingPistonBlock.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 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.level.block.type; + +import org.cloudburstmc.math.vector.Vector3i; +import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; +import org.geysermc.geyser.session.GeyserSession; + +public class MovingPistonBlock extends Block { + public MovingPistonBlock(String javaIdentifier, Builder builder) { + super(javaIdentifier, builder); + } + + @Override + protected void sendBlockUpdatePacket(GeyserSession session, BlockState state, BlockDefinition definition, Vector3i position) { + // Prevent moving_piston from being placed + // It's used for extending piston heads, but it isn't needed on Bedrock and causes pistons to flicker + } +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/PistonBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/PistonBlock.java new file mode 100644 index 000000000..fc54115eb --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/PistonBlock.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 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.level.block.type; + +import org.cloudburstmc.math.vector.Vector3i; +import org.cloudburstmc.nbt.NbtMap; +import org.geysermc.geyser.level.block.Blocks; +import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.level.block.entity.BedrockChunkWantsBlockEntityTag; +import org.geysermc.geyser.translator.level.block.entity.PistonBlockEntity; + +public class PistonBlock extends Block implements BedrockChunkWantsBlockEntityTag { + public PistonBlock(String javaIdentifier, Builder builder) { + super(javaIdentifier, builder); + } + + @Override + public NbtMap createTag(GeyserSession session, Vector3i position, BlockState blockState) { + boolean extended = blockState.getValue(Properties.EXTENDED); + boolean sticky = blockState.is(Blocks.STICKY_PISTON); + return PistonBlockEntity.buildStaticPistonTag(position, extended, sticky); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/SkullBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/SkullBlock.java new file mode 100644 index 000000000..01a757eae --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/SkullBlock.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 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.level.block.type; + +import org.cloudburstmc.math.vector.Vector3i; +import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; +import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.SkullCache; + +public class SkullBlock extends Block { + public SkullBlock(String javaIdentifier, Builder builder) { + super(javaIdentifier, builder); + } + + @Override + protected void sendBlockUpdatePacket(GeyserSession session, BlockState state, BlockDefinition definition, Vector3i position) { + int skullVariant = BlockStateValues.getSkullVariant(state.javaId()); // TODO + if (skullVariant == -1) { + // Skull is gone + session.getSkullCache().removeSkull(position); + } else if (skullVariant == 3) { + // The changed block was a player skull so check if a custom block was defined for this skull + SkullCache.Skull skull = session.getSkullCache().updateSkull(position, state.javaId()); + if (skull != null && skull.getBlockDefinition() != null) { + definition = skull.getBlockDefinition(); + } + } + super.sendBlockUpdatePacket(session, state, definition, position); + } +} 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 64b466f12..66301cef2 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 @@ -424,39 +424,12 @@ public final class BlockRegistryPopulator { // TODO fix this, (no block should have a null hardness) BlockMapping.BlockMappingBuilder builder = BlockMapping.builder(); - JsonNode hardnessNode = entry.getValue().get("block_hardness"); - if (hardnessNode != null) { - builder.hardness(hardnessNode.floatValue()); - } - - JsonNode canBreakWithHandNode = entry.getValue().get("can_break_with_hand"); - if (canBreakWithHandNode != null) { - builder.canBreakWithHand(canBreakWithHandNode.booleanValue()); - } else { - builder.canBreakWithHand(false); - } - - JsonNode collisionIndexNode = entry.getValue().get("collision_index"); - if (hardnessNode != null) { - builder.collisionIndex(collisionIndexNode.intValue()); - } JsonNode pickItemNode = entry.getValue().get("pick_item"); if (pickItemNode != null) { builder.pickItem(pickItemNode.textValue().intern()); } - if (javaId.equals("minecraft:obsidian") || javaId.equals("minecraft:crying_obsidian") || javaId.startsWith("minecraft:respawn_anchor") || javaId.startsWith("minecraft:reinforced_deepslate")) { - builder.pistonBehavior(PistonBehavior.BLOCK); - } else { - JsonNode pistonBehaviorNode = entry.getValue().get("piston_behavior"); - if (pistonBehaviorNode != null) { - builder.pistonBehavior(PistonBehavior.getByName(pistonBehaviorNode.textValue())); - } else { - builder.pistonBehavior(PistonBehavior.NORMAL); - } - } - JsonNode hasBlockEntityNode = entry.getValue().get("has_block_entity"); if (hasBlockEntityNode != null) { builder.isBlockEntity(hasBlockEntityNode.booleanValue()); @@ -475,7 +448,6 @@ public final class BlockRegistryPopulator { } builder.javaIdentifier(javaId); - builder.javaBlockId(uniqueJavaId); BlockRegistries.JAVA_IDENTIFIER_TO_ID.register(javaId, javaRuntimeId); BlockRegistries.JAVA_BLOCKS.register(javaRuntimeId, builder.build()); @@ -547,26 +519,23 @@ public final class BlockRegistryPopulator { int stateRuntimeId = javaBlockState.javaId(); String pistonBehavior = javaBlockState.pistonBehavior(); BlockMapping blockMapping = BlockMapping.builder() - .canBreakWithHand(javaBlockState.canBreakWithHand()) .pickItem(javaBlockState.pickItem()) .isNonVanilla(true) .javaIdentifier(javaId) - .javaBlockId(javaBlockState.stateGroupId()) - .hardness(javaBlockState.blockHardness()) - .pistonBehavior(pistonBehavior == null ? PistonBehavior.NORMAL : PistonBehavior.getByName(pistonBehavior)) - .isBlockEntity(javaBlockState.hasBlockEntity()) .build(); Block.Builder builder = Block.builder() - .destroyTime(javaBlockState.blockHardness()); + .destroyTime(javaBlockState.blockHardness()) + .pushReaction(pistonBehavior == null ? PistonBehavior.NORMAL : PistonBehavior.getByName(pistonBehavior)); if (!javaBlockState.canBreakWithHand()) { builder.requiresCorrectToolForDrops(); } if (javaBlockState.hasBlockEntity()) { builder.setBlockEntity(); } - String cleanJavaIdentifier = BlockUtils.getCleanIdentifier(javaBlockState.identifier()); + Block block = new Block(cleanJavaIdentifier, builder); + String bedrockIdentifier = customBlockState.block().identifier(); if (!cleanJavaIdentifier.equals(cleanIdentifiers.peekLast())) { @@ -574,6 +543,7 @@ public final class BlockRegistryPopulator { cleanIdentifiers.add(cleanJavaIdentifier.intern()); } + BlockRegistries.JAVA_BLOCKS_TO_RENAME.get().add(javaBlockState.stateGroupId(), block); //TODO don't allow duplicates, allow blanks BlockRegistries.JAVA_IDENTIFIER_TO_ID.register(javaId, stateRuntimeId); BlockRegistries.JAVA_BLOCKS.register(stateRuntimeId, blockMapping); 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 0196ac22f..d6ee55965 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,32 +27,19 @@ 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; @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").build(); String javaIdentifier; - /** - * The block ID shared between all different block states of this block. - * NOT the runtime ID! - */ - int javaBlockId; - float hardness; boolean canBreakWithHand; - /** - * The index of this collision in collision.json - */ - int collisionIndex; @Nullable String pickItem; - @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 c76f024af..2fe808070 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 @@ -35,6 +35,7 @@ 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 org.geysermc.geyser.level.block.type.BlockState; import java.util.List; import java.util.Map; @@ -78,6 +79,10 @@ public class BlockMappings implements DefinitionRegistry { return this.javaToBedrockBlocks[javaState]; } + public GeyserBedrockBlock getBedrockBlock(BlockState javaState) { + return this.getBedrockBlock(javaState.javaId()); + } + public GeyserBedrockBlock getVanillaBedrockBlock(int javaState) { if (javaState < 0 || javaState >= this.javaToVanillaBedrockBlocks.length) { return bedrockAir; 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 6da354646..95f5c1cc3 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 @@ -30,7 +30,6 @@ import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.level.block.type.Block; -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; @@ -107,17 +106,6 @@ public final class TagCache { return false; } - /** - * @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 false; - } - /** * @return true if the item tag is present and contains this item stack's Java ID. */ 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 c84126608..44ec7a6b9 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 @@ -180,7 +180,7 @@ public final class WorldCache { // This block may be out of sync with the server // In 1.19.0 Java, you can verify this by trying to mine in spawn protection Vector3i position = entry.getKey(); - ChunkUtils.updateBlockClientSide(session, session.getGeyser().getWorldManager().getBlockAt(session, position), position); + ChunkUtils.updateBlockClientSide(session, session.getGeyser().getWorldManager().blockAt(session, position), position); it.remove(); } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/PistonBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedrockChunkWantsBlockEntityTag.java similarity index 59% rename from core/src/main/java/org/geysermc/geyser/translator/level/block/entity/PistonBlockEntityTranslator.java rename to core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedrockChunkWantsBlockEntityTag.java index a55fa8a62..189fb2c65 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/PistonBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedrockChunkWantsBlockEntityTag.java @@ -27,32 +27,18 @@ package org.geysermc.geyser.translator.level.block.entity; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; -import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.type.BlockState; +import org.geysermc.geyser.session.GeyserSession; /** - * Pistons are a special case where they are only a block entity on Bedrock. + * Implemented only if a block is a block entity in Bedrock and not Java Edition. */ -public class PistonBlockEntityTranslator { +public interface BedrockChunkWantsBlockEntityTag extends RequiresBlockState { /** - * Used in ChunkUtils to determine if the block is a piston. - * + * Get the tag of the Bedrock-only block entity. Used during chunk loading. + * @param position Bedrock position of block. * @param blockState Java BlockState of block. - * @return if block is a piston or not. + * @return Bedrock tag */ - public static boolean isBlock(int blockState) { - return BlockStateValues.getPistonValues().containsKey(blockState); - } - - /** - * Calculates the Nukkit CompoundTag to send to the client on chunk - * - * @param blockState Java block state of block. - * @param position Bedrock position of piston. - * @return Bedrock tag of piston. - */ - public static NbtMap getTag(int blockState, Vector3i position) { - boolean extended = BlockStateValues.getPistonValues().get(blockState); - boolean sticky = BlockStateValues.isStickyPiston(blockState); - return PistonBlockEntity.buildStaticPistonTag(position, extended, sticky); - } + NbtMap createTag(GeyserSession session, Vector3i position, BlockState blockState); } 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 deleted file mode 100644 index 01e2d3e74..000000000 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/BedrockOnlyBlockEntity.java +++ /dev/null @@ -1,82 +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.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; -import org.cloudburstmc.nbt.NbtType; -import org.geysermc.geyser.level.block.BlockStateValues; -import org.geysermc.geyser.level.block.type.BlockState; -import org.geysermc.geyser.session.GeyserSession; - -/** - * Implemented only if a block is a block entity in Bedrock and not Java Edition. - */ -public interface BedrockOnlyBlockEntity extends RequiresBlockState { - /** - * Determines if block is part of class - * @param blockState BlockState to be compared - * @return true if part of the class - */ - boolean isBlock(int blockState); - - /** - * Update the block on Bedrock Edition. - * @param session GeyserConnection. - * @param blockState The Java block state. - * @param position The Bedrock block position. - */ - void updateBlock(GeyserSession session, BlockState blockState, Vector3i position); - - /** - * Get the tag of the Bedrock-only block entity - * @param position Bedrock position of block. - * @param blockState Java BlockState of block. - * @return Bedrock tag, or null if not a Bedrock-only Block Entity - */ - 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)) { - return PistonBlockEntityTranslator.getTag(blockState, position); - } else if (BlockStateValues.isCauldron(blockState)) { - // As of 1.18.30: this is required to make rendering not look weird on chunk load (lava and snow cauldrons look dim) - return NbtMap.builder() - .putString("id", "Cauldron") - .putByte("isMovable", (byte) 0) - .putShort("PotionId", (short) -1) - .putShort("PotionType", (short) -1) - .putList("Items", NbtType.END, NbtList.EMPTY) - .putInt("x", position.getX()) - .putInt("y", position.getY()) - .putInt("z", position.getZ()) - .build(); - } - return null; - } -} diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DoubleChestBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/DoubleChestBlockEntityTranslator.java index 63c5f71f3..102f4a0e6 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,33 +25,20 @@ package org.geysermc.geyser.translator.level.block.entity; -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.property.ChestType; import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.level.physics.Direction; 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 + * Chests have more block entity properties in Bedrock, which is solved by implementing the BedrockChunkWantsBlockEntityTag */ @BlockEntity(type = { BlockEntityType.CHEST, BlockEntityType.TRAPPED_CHEST }) -public class DoubleChestBlockEntityTranslator extends BlockEntityTranslator implements BedrockOnlyBlockEntity { - @Override - public boolean isBlock(int blockState) { - return BlockStateValues.getDoubleChestValues().containsKey(blockState); - } - - @Override - public void updateBlock(GeyserSession session, BlockState blockState, Vector3i position) { - NbtMapBuilder tagBuilder = getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId(BlockEntityType.CHEST), position.getX(), position.getY(), position.getZ()); - translateTag(session, tagBuilder, null, blockState); - BlockEntityUtils.updateBlockEntity(session, tagBuilder.build(), position); - } +public class DoubleChestBlockEntityTranslator extends BlockEntityTranslator { @Override public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) { @@ -71,7 +58,7 @@ public class DoubleChestBlockEntityTranslator extends BlockEntityTranslator impl public static void translateChestValue(NbtMapBuilder builder, BlockState state, int x, int z) { // Calculate the position of the other chest based on the Java block state Direction facing = state.getValue(Properties.HORIZONTAL_FACING); - boolean isLeft = state.getValue(Properties.CHEST_TYPE).equals("left"); //TODO enum + boolean isLeft = state.getValue(Properties.CHEST_TYPE) == ChestType.LEFT; switch (facing) { case EAST -> z = z + (isLeft ? 1 : -1); case WEST -> z = z + (isLeft ? -1 : 1); 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 e09f6ae42..abe3a197e 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,11 @@ package org.geysermc.geyser.translator.level.block.entity; +import it.unimi.dsi.fastutil.objects.*; +import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.level.block.type.Block; +import org.geysermc.geyser.level.block.type.BlockState; +import org.geysermc.geyser.level.block.type.PistonBlock; import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType; import org.cloudburstmc.math.vector.Vector3d; import org.cloudburstmc.math.vector.Vector3f; @@ -33,9 +37,6 @@ import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; -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.geyser.api.util.PlatformType; import org.geysermc.geyser.level.block.BlockStateValues; @@ -69,7 +70,7 @@ public class PistonBlockEntity { /** * A map of attached block positions to Java ids. */ - private final Object2IntMap attachedBlocks = new Object2IntOpenHashMap<>(); + private final Object2ObjectMap attachedBlocks = new Object2ObjectOpenHashMap<>(); /** * A flattened array of the positions of attached blocks, stored in XYZ order. */ @@ -158,7 +159,7 @@ public class PistonBlockEntity { BlockEntityUtils.updateBlockEntity(session, buildPistonTag(), position); } - public void setAction(PistonValueType action, Object2IntMap attachedBlocks) { + public void setAction(PistonValueType action, Map attachedBlocks) { // Don't check if this.action == action, since on some Paper versions BlockPistonRetractEvent is called multiple times // with the first 1-2 events being empty. placeFinalBlocks(); @@ -255,13 +256,13 @@ public class PistonBlockEntity { if (!blocksChecked.add(blockPos)) { continue; } - int blockId = session.getGeyser().getWorldManager().getBlockAt(session, blockPos); - if (blockId == Block.JAVA_AIR_ID) { + BlockState state = session.getGeyser().getWorldManager().blockAt(session, blockPos); + if (state.block() == Blocks.AIR) { continue; } - if (BlockStateValues.canPistonMoveBlock(blockId, action == PistonValueType.PUSHING)) { - attachedBlocks.put(blockPos, blockId); - if (BlockStateValues.isBlockSticky(blockId)) { + if (BlockStateValues.canPistonMoveBlock(state, action == PistonValueType.PUSHING)) { + attachedBlocks.put(blockPos, state); + if (BlockStateValues.isBlockSticky(state)) { // For honey blocks and slime blocks check the blocks adjacent to it for (Direction direction : Direction.VALUES) { Vector3i offset = direction.getUnitVector(); @@ -278,13 +279,13 @@ public class PistonBlockEntity { if (action == PistonValueType.PULLING && position.add(directionOffset).equals(adjacentPos)) { continue; } - int adjacentBlockId = session.getGeyser().getWorldManager().getBlockAt(session, adjacentPos); - if (adjacentBlockId != Block.JAVA_AIR_ID && BlockStateValues.isBlockAttached(blockId, adjacentBlockId) && BlockStateValues.canPistonMoveBlock(adjacentBlockId, false)) { + BlockState adjacentBlockState = session.getGeyser().getWorldManager().blockAt(session, adjacentPos); + if (adjacentBlockState.block() != Blocks.AIR && BlockStateValues.isBlockAttached(state, adjacentBlockState) && BlockStateValues.canPistonMoveBlock(adjacentBlockState, false)) { // If it is another slime/honey block we need to check its adjacent blocks - if (BlockStateValues.isBlockSticky(adjacentBlockId)) { + if (BlockStateValues.isBlockSticky(adjacentBlockState)) { blocksToCheck.add(adjacentPos); } else { - attachedBlocks.put(adjacentPos, adjacentBlockId); + attachedBlocks.put(adjacentPos, adjacentBlockState); blocksChecked.add(adjacentPos); blocksToCheck.add(adjacentPos.add(movement)); } @@ -293,7 +294,7 @@ public class PistonBlockEntity { } // Check next block in line blocksToCheck.add(blockPos.add(movement)); - } else if (!BlockStateValues.canPistonDestroyBlock(blockId)) { + } else if (!BlockStateValues.canPistonDestroyBlock(state)) { // Block can't be moved or destroyed, so it blocks all block movement moveBlocks = false; break; @@ -350,24 +351,24 @@ public class PistonBlockEntity { playerBoundingBox.setSizeZ(playerBoundingBox.getSizeZ() - shrink.getZ()); // Resolve collision with the piston head - int pistonHeadId = BlockStateValues.getPistonHead(orientation); + BlockState pistonHeadId = BlockState.of(BlockStateValues.getPistonHead(orientation)); pushPlayerBlock(pistonHeadId, getPistonHeadPos().toDouble(), blockMovement, playerBoundingBox); // Resolve collision with any attached moving blocks, but skip slime blocks // This prevents players from being launched by slime blocks covered by other blocks - for (Object2IntMap.Entry entry : attachedBlocks.object2IntEntrySet()) { - int blockId = entry.getIntValue(); - if (blockId != BlockStateValues.JAVA_SLIME_BLOCK_ID) { + for (Map.Entry entry : Object2ObjectMaps.fastIterable(attachedBlocks)) { + BlockState state = entry.getValue(); + if (!state.is(Blocks.SLIME_BLOCK)) { Vector3d blockPos = entry.getKey().toDouble(); - pushPlayerBlock(blockId, blockPos, blockMovement, playerBoundingBox); + pushPlayerBlock(state, blockPos, blockMovement, playerBoundingBox); } } // Resolve collision with slime blocks - for (Object2IntMap.Entry entry : attachedBlocks.object2IntEntrySet()) { - int blockId = entry.getIntValue(); - if (blockId == BlockStateValues.JAVA_SLIME_BLOCK_ID) { + for (Map.Entry entry : Object2ObjectMaps.fastIterable(attachedBlocks)) { + BlockState state = entry.getValue(); + if (state.is(Blocks.SLIME_BLOCK)) { Vector3d blockPos = entry.getKey().toDouble(); - pushPlayerBlock(blockId, blockPos, blockMovement, playerBoundingBox); + pushPlayerBlock(state, blockPos, blockMovement, playerBoundingBox); } } @@ -463,7 +464,7 @@ public class PistonBlockEntity { return maxIntersection; } - private void pushPlayerBlock(int javaId, Vector3d startingPos, double blockMovement, BoundingBox playerBoundingBox) { + private void pushPlayerBlock(BlockState state, Vector3d startingPos, double blockMovement, BoundingBox playerBoundingBox) { PistonCache pistonCache = session.getPistonCache(); Vector3d movement = getMovement().toDouble(); // Check if the player collides with the movingBlock block entity @@ -471,14 +472,14 @@ public class PistonBlockEntity { if (SOLID_BOUNDING_BOX.checkIntersection(finalBlockPos, playerBoundingBox)) { pistonCache.setPlayerCollided(true); - if (javaId == BlockStateValues.JAVA_SLIME_BLOCK_ID) { + if (state.is(Blocks.SLIME_BLOCK)) { pistonCache.setPlayerSlimeCollision(true); applySlimeBlockMotion(finalBlockPos, Vector3d.from(playerBoundingBox.getMiddleX(), playerBoundingBox.getMiddleY(), playerBoundingBox.getMiddleZ())); } } Vector3d blockPos = startingPos.add(movement.mul(blockMovement)); - if (javaId == BlockStateValues.JAVA_HONEY_BLOCK_ID && isPlayerAttached(blockPos, playerBoundingBox)) { + if (state.is(Blocks.HONEY_BLOCK) && isPlayerAttached(blockPos, playerBoundingBox)) { pistonCache.setPlayerCollided(true); pistonCache.setPlayerAttachedToHoney(true); @@ -486,7 +487,7 @@ public class PistonBlockEntity { pistonCache.displacePlayer(movement.mul(delta)); } else { // Move the player out of collision - BlockCollision blockCollision = BlockRegistries.COLLISIONS.get(javaId); + BlockCollision blockCollision = BlockRegistries.COLLISIONS.get(state.javaId()); if (blockCollision != null) { Vector3d extend = movement.mul(Math.min(1 - blockMovement, 0.5)); Direction movementDirection = orientation; @@ -499,7 +500,7 @@ public class PistonBlockEntity { pistonCache.setPlayerCollided(true); pistonCache.displacePlayer(movement.mul(intersection + 0.01d)); - if (javaId == BlockStateValues.JAVA_SLIME_BLOCK_ID) { + if (state.is(Blocks.SLIME_BLOCK)) { pistonCache.setPlayerSlimeCollision(true); applySlimeBlockMotion(blockPos, Vector3d.from(playerBoundingBox.getMiddleX(), playerBoundingBox.getMiddleY(), playerBoundingBox.getMiddleZ())); } @@ -509,7 +510,7 @@ public class PistonBlockEntity { } private BlockCollision getCollision(Vector3i blockPos) { - return BlockUtils.getCollision(getAttachedBlockId(blockPos)); + return BlockUtils.getCollision(getAttachedBlockId(blockPos).javaId()); } /** @@ -533,7 +534,7 @@ public class PistonBlockEntity { double y = blockPos.getY() + movementVec.getY() * movementProgress; double z = blockPos.getZ() + movementVec.getZ() * movementProgress; double adjustedMovement = blockCollision.computeCollisionOffset(x, y, z, boundingBox, axis, movement); - if (getAttachedBlockId(blockPos) == BlockStateValues.JAVA_SLIME_BLOCK_ID && adjustedMovement != movement) { + if (getAttachedBlockId(blockPos).is(Blocks.SLIME_BLOCK) && adjustedMovement != movement) { session.getPistonCache().setPlayerSlimeCollision(true); } return adjustedMovement; @@ -557,11 +558,11 @@ public class PistonBlockEntity { return false; } - private int getAttachedBlockId(Vector3i blockPos) { + private BlockState getAttachedBlockId(Vector3i blockPos) { if (blockPos.equals(getPistonHeadPos())) { - return BlockStateValues.getPistonHead(orientation); + return BlockState.of(BlockStateValues.getPistonHead(orientation)); } else { - return attachedBlocks.getOrDefault(blockPos, Block.JAVA_AIR_ID); + return attachedBlocks.getOrDefault(blockPos, BlockState.of(Block.JAVA_AIR_ID)); //FIXME } } @@ -582,12 +583,12 @@ public class PistonBlockEntity { playerBoundingBox.setSizeX(playerBoundingBox.getSizeX() + 0.5); playerBoundingBox.setSizeZ(playerBoundingBox.getSizeZ() + 0.5); } - attachedBlocks.forEach((blockPos, javaId) -> { + attachedBlocks.forEach((blockPos, state) -> { Vector3i newPos = blockPos.add(movement); if (SOLID_BOUNDING_BOX.checkIntersection(blockPos.toDouble(), playerBoundingBox) || SOLID_BOUNDING_BOX.checkIntersection(newPos.toDouble(), playerBoundingBox)) { session.getPistonCache().setPlayerCollided(true); - if (javaId == BlockStateValues.JAVA_SLIME_BLOCK_ID) { + if (state.is(Blocks.SLIME_BLOCK)) { session.getPistonCache().setPlayerSlimeCollision(true); } // Don't place moving blocks that collide with the player @@ -603,7 +604,7 @@ public class PistonBlockEntity { updateBlockPacket.setDataLayer(0); session.sendUpstreamPacket(updateBlockPacket); // Update moving block with correct details - BlockEntityUtils.updateBlockEntity(session, buildMovingBlockTag(newPos, javaId, position), newPos); + BlockEntityUtils.updateBlockEntity(session, buildMovingBlockTag(newPos, state, position), newPos); }); } @@ -773,13 +774,13 @@ public class PistonBlockEntity { * Create a moving block tag of a block that will be moved by a piston * * @param position The ending position of the block (The location of the movingBlock block entity) - * @param javaId The Java Id of the block that is moving + * @param state The Java BlockState of the block that is moving * @param pistonPosition The position for the base of the piston that's moving the block * @return A moving block data tag */ - private NbtMap buildMovingBlockTag(Vector3i position, int javaId, Vector3i pistonPosition) { + private NbtMap buildMovingBlockTag(Vector3i position, BlockState state, Vector3i pistonPosition) { // Get Bedrock block state data - NbtMap movingBlock = session.getBlockMappings().getBedrockBlock(javaId).getState(); + NbtMap movingBlock = session.getBlockMappings().getBedrockBlock(state).getState(); NbtMapBuilder builder = NbtMap.builder() .putString("id", "MovingBlock") .putBoolean("expanding", action == PistonValueType.PUSHING) @@ -791,8 +792,8 @@ public class PistonBlockEntity { .putInt("x", position.getX()) .putInt("y", position.getY()) .putInt("z", position.getZ()); - if (PistonBlockEntityTranslator.isBlock(javaId)) { - builder.putCompound("movingEntity", PistonBlockEntityTranslator.getTag(javaId, position)); + if (state.block() instanceof PistonBlock piston) { + builder.putCompound("movingEntity", piston.createTag(session, position, state)); } return builder.build(); } 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 9cb3fb455..507d67ba5 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,13 +25,12 @@ package org.geysermc.geyser.translator.protocol.bedrock; -import org.geysermc.geyser.level.block.type.Block; -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; import org.geysermc.geyser.entity.type.ItemFrameEntity; import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.type.BlockMapping; import org.geysermc.geyser.registry.type.ItemMapping; @@ -39,6 +38,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.InventoryUtils; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; @Translator(packet = BlockPickRequestPacket.class) public class BedrockBlockPickRequestTranslator 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 36f1d3d65..b7201762f 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,23 +25,25 @@ package org.geysermc.geyser.translator.protocol.java.level; -import org.geysermc.geyser.level.block.type.Block; -import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.*; -import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundBlockEventPacket; +import it.unimi.dsi.fastutil.objects.Object2ObjectMaps; import org.cloudburstmc.math.vector.Vector3i; -import org.cloudburstmc.nbt.NbtMap; 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.api.util.PlatformType; import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.geyser.level.block.type.Block; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.level.physics.Direction; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.PistonCache; +import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator; import org.geysermc.geyser.translator.level.block.entity.PistonBlockEntity; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.*; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundBlockEventPacket; @Translator(packet = ClientboundBlockEventPacket.class) public class JavaBlockEventTranslator extends PacketTranslator { @@ -63,7 +65,7 @@ public class JavaBlockEventTranslator extends PacketTranslator { - blockEventPacket.setEventData(BlockStateValues.getNoteblockPitch(blockState)); + blockEventPacket.setEventData(BlockState.of(blockState).getValue(Properties.NOTE)); session.sendUpstreamPacket(blockEventPacket); }); } else if (value instanceof PistonValue pistonValue) { @@ -90,7 +92,7 @@ public class JavaBlockEventTranslator extends PacketTranslator new PistonBlockEntity(session, pos, direction, true, true)); if (blockEntity.getAction() != action) { - blockEntity.setAction(action, Object2IntMaps.emptyMap()); + blockEntity.setAction(action, Object2ObjectMaps.emptyMap()); } } } else { @@ -110,11 +112,7 @@ public class JavaBlockEventTranslator extends PacketTranslator 0; case WEST -> 1; 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 e54fe5896..bd7096d2b 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 @@ -41,7 +41,6 @@ import org.cloudburstmc.protocol.bedrock.packet.LevelChunkPacket; import org.geysermc.erosion.util.LecternUtils; import org.geysermc.geyser.entity.type.ItemFrameEntity; import org.geysermc.geyser.level.BedrockDimension; -import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.level.block.type.BlockState; @@ -53,7 +52,7 @@ import org.geysermc.geyser.level.chunk.bitarray.SingletonBitArray; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.level.BiomeTranslator; -import org.geysermc.geyser.translator.level.block.entity.BedrockOnlyBlockEntity; +import org.geysermc.geyser.translator.level.block.entity.BedrockChunkWantsBlockEntityTag; import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator; import org.geysermc.geyser.translator.level.block.entity.SkullBlockEntityTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator; @@ -193,11 +192,12 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator> 8) & 0xF), (packet.getZ() << 4) + ((yzx >> 4) & 0xF)), - javaId + state )); } } @@ -253,7 +253,9 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator> 8) & 0xF), (packet.getZ() << 4) + ((yzx >> 4) & 0xF)), - javaPalette.idToState(paletteId) + state )); } } 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 ec7f45c8d..1462378e9 100644 --- a/core/src/main/java/org/geysermc/geyser/util/BlockEntityUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/BlockEntityUtils.java @@ -31,25 +31,13 @@ import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket; import org.geysermc.geyser.registry.Registries; 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; import java.util.Map; public class BlockEntityUtils { - /** - * A list of all block entities that require the Java block state in order to fill out their block entity information. - * This list will be smaller with cache sections on as we don't need to double-cache data - */ - public static final List BEDROCK_ONLY_BLOCK_ENTITIES = List.of( - (BedrockOnlyBlockEntity) Registries.BLOCK_ENTITIES.get().get(BlockEntityType.CHEST), - new FlowerPotBlockEntityTranslator() - ); - /** * Contains a list of irregular block entity name translations that can't be fit into the regex */ 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 a1e956ace..5504d01a8 100644 --- a/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java @@ -33,24 +33,19 @@ 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.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.packet.LevelChunkPacket; import org.cloudburstmc.protocol.bedrock.packet.NetworkChunkPublisherUpdatePacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.geyser.entity.type.ItemFrameEntity; import org.geysermc.geyser.level.BedrockDimension; import org.geysermc.geyser.level.JavaDimension; -import org.geysermc.geyser.level.block.BlockStateValues; -import org.geysermc.geyser.level.block.type.Block; +import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.level.chunk.BlockStorage; import org.geysermc.geyser.level.chunk.GeyserChunkSection; import org.geysermc.geyser.level.chunk.bitarray.SingletonBitArray; -import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.session.cache.SkullCache; import org.geysermc.geyser.text.GeyserLocale; -import org.geysermc.geyser.translator.level.block.entity.BedrockOnlyBlockEntity; @UtilityClass public class ChunkUtils { @@ -119,18 +114,30 @@ public class ChunkUtils { * @param position the position of the block */ public static void updateBlock(GeyserSession session, int blockState, Vector3i position) { - updateBlockClientSide(session, blockState, position); + updateBlockClientSide(session, BlockState.of(blockState), position); session.getChunkCache().updateBlock(position.getX(), position.getY(), position.getZ(), blockState); } + /** + * Sends a block update to the Bedrock client. If the platform does not have an integrated world manager, this also + * adds that block to the cache. + * @param session the Bedrock session to send/register the block to + * @param blockState the Java block state of the block + * @param position the position of the block + */ + public static void updateBlock(GeyserSession session, BlockState blockState, Vector3i position) { + updateBlockClientSide(session, blockState, position); + session.getChunkCache().updateBlock(position.getX(), position.getY(), position.getZ(), blockState.javaId()); + } + /** * Updates a block, but client-side only. */ - public static void updateBlockClientSide(GeyserSession session, int blockState, Vector3i position) { + public static void updateBlockClientSide(GeyserSession session, BlockState blockState, Vector3i position) { // Checks for item frames so they aren't tripped up and removed ItemFrameEntity itemFrameEntity = ItemFrameEntity.getItemFrameEntity(session, position); if (itemFrameEntity != null) { - if (blockState == Block.JAVA_AIR_ID) { // Item frame is still present and no block overrides that; refresh it + if (blockState.is(Blocks.AIR)) { // Item frame is still present and no block overrides that; refresh it itemFrameEntity.updateBlock(true); // Still update the chunk cache with the new block if updateBlock is called return; @@ -138,91 +145,7 @@ public class ChunkUtils { // Otherwise, let's still store our reference to the item frame, but let the new block take precedence for now } - BlockDefinition definition = session.getBlockMappings().getBedrockBlock(blockState); - - int skullVariant = BlockStateValues.getSkullVariant(blockState); - if (skullVariant == -1) { - // Skull is gone - session.getSkullCache().removeSkull(position); - } else if (skullVariant == 3) { - // The changed block was a player skull so check if a custom block was defined for this skull - SkullCache.Skull skull = session.getSkullCache().updateSkull(position, blockState); - if (skull != null && skull.getBlockDefinition() != null) { - definition = skull.getBlockDefinition(); - } - } - - // Prevent moving_piston from being placed - // It's used for extending piston heads, but it isn't needed on Bedrock and causes pistons to flicker - if (!BlockStateValues.isMovingPiston(blockState)) { - UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); - updateBlockPacket.setDataLayer(0); - updateBlockPacket.setBlockPosition(position); - updateBlockPacket.setDefinition(definition); - updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS); - updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); - session.sendUpstreamPacket(updateBlockPacket); - - UpdateBlockPacket waterPacket = new UpdateBlockPacket(); - waterPacket.setDataLayer(1); - waterPacket.setBlockPosition(position); - if (BlockRegistries.WATERLOGGED.get().get(blockState)) { - waterPacket.setDefinition(session.getBlockMappings().getBedrockWater()); - } else { - waterPacket.setDefinition(session.getBlockMappings().getBedrockAir()); - } - session.sendUpstreamPacket(waterPacket); - } - - // Extended collision boxes for custom blocks - if (!session.getBlockMappings().getExtendedCollisionBoxes().isEmpty()) { - int aboveBlock = session.getGeyser().getWorldManager().getBlockAt(session, position.getX(), position.getY() + 1, position.getZ()); - BlockDefinition aboveBedrockExtendedCollisionDefinition = session.getBlockMappings().getExtendedCollisionBoxes().get(blockState); - int belowBlock = session.getGeyser().getWorldManager().getBlockAt(session, position.getX(), position.getY() - 1, position.getZ()); - BlockDefinition belowBedrockExtendedCollisionDefinition = session.getBlockMappings().getExtendedCollisionBoxes().get(belowBlock); - if (belowBedrockExtendedCollisionDefinition != null && blockState == Block.JAVA_AIR_ID) { - UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); - updateBlockPacket.setDataLayer(0); - updateBlockPacket.setBlockPosition(position); - updateBlockPacket.setDefinition(belowBedrockExtendedCollisionDefinition); - updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); - session.sendUpstreamPacket(updateBlockPacket); - } else if (aboveBedrockExtendedCollisionDefinition != null && aboveBlock == Block.JAVA_AIR_ID) { - UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); - updateBlockPacket.setDataLayer(0); - updateBlockPacket.setBlockPosition(position.add(0, 1, 0)); - updateBlockPacket.setDefinition(aboveBedrockExtendedCollisionDefinition); - updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); - session.sendUpstreamPacket(updateBlockPacket); - } else if (aboveBlock == Block.JAVA_AIR_ID) { - UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); - updateBlockPacket.setDataLayer(0); - updateBlockPacket.setBlockPosition(position.add(0, 1, 0)); - updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockAir()); - updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); - session.sendUpstreamPacket(updateBlockPacket); - } - } - - BlockStateValues.getLecternBookStates().handleBlockChange(session, blockState, position); - - // Iterates through all Bedrock-only block entity translators and determines if a manual block entity packet - // needs to be sent - for (BedrockOnlyBlockEntity bedrockOnlyBlockEntity : BlockEntityUtils.BEDROCK_ONLY_BLOCK_ENTITIES) { - if (bedrockOnlyBlockEntity.isBlock(blockState)) { - // Flower pots are block entities only in Bedrock and are not updated anywhere else like note blocks - bedrockOnlyBlockEntity.updateBlock(session, BlockState.of(blockState), position); //TODO blockState - 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); - } + blockState.block().updateBlock(session, blockState, position); } public static void sendEmptyChunk(GeyserSession session, int chunkX, int chunkZ, boolean forceUpdate) { From a439f3e3d7a6a9e16f3e6dea9df4dfb0df37b7d4 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Fri, 17 May 2024 21:14:59 -0400 Subject: [PATCH 016/233] Fix compilation for Spigot --- .../spigot/world/GeyserPistonListener.java | 17 ++++++------ .../erosion/GeyserboundPacketHandlerImpl.java | 4 +-- .../geyser/level/block/type/BlockState.java | 10 +++++++ .../block/entity/BlockEntityTranslator.java | 5 ++++ .../level/block/entity/PistonBlockEntity.java | 27 ++++++------------- 5 files changed, 34 insertions(+), 29 deletions(-) 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 61c0d5fe8..2a6dc7a81 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,10 +25,8 @@ package org.geysermc.geyser.platform.spigot.world; -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; +import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; @@ -40,13 +38,16 @@ import org.bukkit.event.Listener; import org.bukkit.event.block.BlockPistonEvent; import org.bukkit.event.block.BlockPistonExtendEvent; import org.bukkit.event.block.BlockPistonRetractEvent; +import org.cloudburstmc.math.vector.Vector3i; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.level.physics.Direction; import org.geysermc.geyser.platform.spigot.world.manager.GeyserSpigotWorldManager; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.PistonCache; import org.geysermc.geyser.translator.level.block.entity.PistonBlockEntity; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType; import java.util.List; import java.util.Map; @@ -85,7 +86,7 @@ public class GeyserPistonListener implements Listener { PistonValueType type = isExtend ? PistonValueType.PUSHING : PistonValueType.PULLING; boolean sticky = event.isSticky(); - Object2IntMap attachedBlocks = new Object2IntArrayMap<>(); + Object2ObjectMap attachedBlocks = new Object2ObjectArrayMap<>(); boolean blocksFilled = false; for (Map.Entry entry : geyser.getSessionManager().getSessions().entrySet()) { @@ -108,10 +109,10 @@ public class GeyserPistonListener implements Listener { List blocks = isExtend ? ((BlockPistonExtendEvent) event).getBlocks() : ((BlockPistonRetractEvent) event).getBlocks(); for (Block block : blocks) { Location attachedLocation = block.getLocation(); - int blockId = worldManager.getBlockNetworkId(block); + BlockState state = BlockState.of(worldManager.getBlockNetworkId(block)); // Ignore blocks that will be destroyed - if (BlockStateValues.canPistonMoveBlock(blockId, isExtend)) { - attachedBlocks.put(getVector(attachedLocation), blockId); + if (BlockStateValues.canPistonMoveBlock(state, isExtend)) { + attachedBlocks.put(getVector(attachedLocation), state); } } blocksFilled = true; 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 6e22fd430..62ecaa1e9 100644 --- a/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java +++ b/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java @@ -30,8 +30,8 @@ import it.unimi.dsi.fastutil.Pair; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.Getter; import lombok.Setter; import org.cloudburstmc.math.vector.Vector3i; @@ -157,7 +157,7 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke .stream() .map(entry -> Pair.of(entry.getKey(), BlockState.of(entry.getIntValue()))) .filter(pair -> BlockStateValues.canPistonMoveBlock(pair.value(), isExtend)); - Object2ObjectMap attachedBlocks = new Object2ObjectOpenHashMap<>(); + Object2ObjectMap attachedBlocks = new Object2ObjectArrayMap<>(); stream.forEach(pair -> attachedBlocks.put(pair.key(), pair.value())); session.executeInEventLoop(() -> { diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java index 23e89d99f..de4806efa 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java @@ -62,6 +62,16 @@ public final class BlockState { return this.block == block; } + private String paramsToString() { + StringBuilder builder = new StringBuilder(); + var it = this.states.entrySet().iterator(); + while (it.hasNext()) { + var entry = it.next(); + builder.append(entry.getKey()).append("=").append(entry.getValue()); + } + return builder.toString(); + } + public static BlockState of(int javaId) { return BlockRegistries.BLOCK_STATES.get(javaId); } 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 5def51e01..ae44dd134 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 @@ -26,6 +26,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; import org.geysermc.geyser.level.block.type.BlockState; @@ -56,6 +57,10 @@ public abstract class BlockEntityTranslator { return getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId(type), x, y, z); } + public static NbtMapBuilder getConstantBedrockTag(String bedrockId, Vector3i position) { + return getConstantBedrockTag(bedrockId, position.getX(), position.getY(), position.getZ()); + } + public static NbtMapBuilder getConstantBedrockTag(String bedrockId, int x, int y, int z) { return NbtMap.builder() .putInt("x", x) 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 abe3a197e..14282228b 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,6 +25,7 @@ package org.geysermc.geyser.translator.level.block.entity; +import it.unimi.dsi.fastutil.ints.IntArrays; import it.unimi.dsi.fastutil.objects.*; import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.level.block.type.Block; @@ -74,7 +75,7 @@ public class PistonBlockEntity { /** * A flattened array of the positions of attached blocks, stored in XYZ order. */ - private int[] flattenedAttachedBlocks = new int[0]; + private int[] flattenedAttachedBlocks = IntArrays.EMPTY_ARRAY; private boolean placedFinalBlocks = true; @@ -732,18 +733,14 @@ public class PistonBlockEntity { * @return A piston data tag */ private NbtMap buildPistonTag() { - NbtMapBuilder builder = NbtMap.builder() - .putString("id", "PistonArm") + NbtMapBuilder builder = BlockEntityTranslator.getConstantBedrockTag("PistonArm", position) .putIntArray("AttachedBlocks", flattenedAttachedBlocks) .putFloat("Progress", progress) .putFloat("LastProgress", lastProgress) .putByte("NewState", getState()) .putByte("State", getState()) .putBoolean("Sticky", sticky) - .putBoolean("isMovable", false) - .putInt("x", position.getX()) - .putInt("y", position.getY()) - .putInt("z", position.getZ()); + .putBoolean("isMovable", false); return builder.build(); } @@ -756,17 +753,13 @@ public class PistonBlockEntity { * @return A piston data tag for a fully extended/retracted piston */ public static NbtMap buildStaticPistonTag(Vector3i position, boolean extended, boolean sticky) { - NbtMapBuilder builder = NbtMap.builder() - .putString("id", "PistonArm") + NbtMapBuilder builder = BlockEntityTranslator.getConstantBedrockTag("PistonArm", position) .putFloat("Progress", extended ? 1.0f : 0.0f) .putFloat("LastProgress", extended ? 1.0f : 0.0f) .putByte("NewState", (byte) (extended ? 2 : 0)) .putByte("State", (byte) (extended ? 2 : 0)) .putBoolean("Sticky", sticky) - .putBoolean("isMovable", false) - .putInt("x", position.getX()) - .putInt("y", position.getY()) - .putInt("z", position.getZ()); + .putBoolean("isMovable", false); return builder.build(); } @@ -781,17 +774,13 @@ public class PistonBlockEntity { private NbtMap buildMovingBlockTag(Vector3i position, BlockState state, Vector3i pistonPosition) { // Get Bedrock block state data NbtMap movingBlock = session.getBlockMappings().getBedrockBlock(state).getState(); - NbtMapBuilder builder = NbtMap.builder() - .putString("id", "MovingBlock") + NbtMapBuilder builder = BlockEntityTranslator.getConstantBedrockTag("MovingBlock", position) .putBoolean("expanding", action == PistonValueType.PUSHING) .putCompound("movingBlock", movingBlock) .putBoolean("isMovable", true) .putInt("pistonPosX", pistonPosition.getX()) .putInt("pistonPosY", pistonPosition.getY()) - .putInt("pistonPosZ", pistonPosition.getZ()) - .putInt("x", position.getX()) - .putInt("y", position.getY()) - .putInt("z", position.getZ()); + .putInt("pistonPosZ", pistonPosition.getZ()); if (state.block() instanceof PistonBlock piston) { builder.putCompound("movingEntity", piston.createTag(session, position, state)); } From 8b7703154ef7b7df82e42cd7ce62e0211b14b3d6 Mon Sep 17 00:00:00 2001 From: chris Date: Sat, 18 May 2024 21:13:00 +0200 Subject: [PATCH 017/233] Resolve issue when trying to transfer a Geyser player (#4673) --- .../main/java/org/geysermc/geyser/session/GeyserSession.java | 3 +++ gradle/libs.versions.toml | 2 +- 2 files changed, 4 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 617087f71..2b7ec0a97 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -896,6 +896,9 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { this.downstream.getSession().setFlag(BuiltinFlags.ATTEMPT_SRV_RESOLVE, resolveSrv); } + // Disable automatic creation of a new TcpClientSession when transferring - we don't use that functionality. + this.downstream.getSession().setFlag(MinecraftConstants.FOLLOW_TRANSFERS, false); + if (geyser.getConfig().getRemote().isUseProxyProtocol()) { downstream.setFlag(BuiltinFlags.ENABLE_CLIENT_PROXY_PROTOCOL, true); downstream.setFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS, upstream.getAddress()); diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 65a5e3a52..dee170705 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 = "e5b0bcc" -mcprotocollib = "42ea4a4" # Revert from jitpack after release +mcprotocollib = "a1b559d" # Revert from jitpack after release adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From 6c904b2378e3e34e215c729001d97c9155c537c5 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sat, 18 May 2024 16:37:06 -0400 Subject: [PATCH 018/233] It's almost done. --- .../java/org/geysermc/geyser/GeyserImpl.java | 8 +- .../entity/type/FurnaceMinecartEntity.java | 8 +- .../entity/type/SpawnerMinecartEntity.java | 4 +- .../erosion/GeyserboundPacketHandlerImpl.java | 2 +- .../holder/BlockInventoryHolder.java | 22 +- .../java/org/geysermc/geyser/item/Items.java | 1851 +++++++++-------- .../geysermc/geyser/item/type/BannerItem.java | 5 +- .../geysermc/geyser/item/type/BlockItem.java | 23 +- .../geyser/item/type/DecoratedPotItem.java | 5 +- .../org/geysermc/geyser/item/type/Item.java | 35 +- .../geyser/item/type/PlayerHeadItem.java | 7 +- .../geyser/item/type/ShulkerBoxItem.java | 5 +- .../geyser/level/block/BlockStateValues.java | 49 - .../geysermc/geyser/level/block/Blocks.java | 14 +- .../geyser/level/block/property/Property.java | 4 + .../geyser/level/block/type/Block.java | 81 +- .../geyser/level/block/type/BlockState.java | 17 +- .../level/block/type/FlowerPotBlock.java | 2 +- .../geyser/level/block/type/FurnaceBlock.java | 56 + .../geyser/level/block/type/HoneyBlock.java | 45 + .../geyser/level/block/type/SpawnerBlock.java | 45 + .../geyser/level/block/type/WaterBlock.java | 41 + .../geyser/registry/BlockRegistries.java | 1 + .../geysermc/geyser/registry/Registries.java | 1 + .../loader/CollisionRegistryLoader.java | 2 +- .../populator/BlockRegistryPopulator.java | 65 +- .../geyser/registry/type/BlockMapping.java | 35 - .../geyser/session/GeyserSession.java | 3 +- .../AbstractBlockInventoryTranslator.java | 5 +- .../inventory/AnvilInventoryTranslator.java | 3 +- .../Generic3X3InventoryTranslator.java | 3 +- .../inventory/ShulkerInventoryTranslator.java | 4 +- .../chest/SingleChestInventoryTranslator.java | 4 +- .../level/block/entity/PistonBlockEntity.java | 7 +- .../BedrockBlockPickRequestTranslator.java | 31 +- ...BedrockInventoryTransactionTranslator.java | 6 +- .../java/level/JavaBlockUpdateTranslator.java | 10 +- .../JavaLevelChunkWithLightTranslator.java | 5 +- .../geysermc/geyser/util/InventoryUtils.java | 32 +- .../geysermc/geyser/util/StatisticsUtils.java | 2 +- 40 files changed, 1359 insertions(+), 1189 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/type/FurnaceBlock.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/type/HoneyBlock.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/type/SpawnerBlock.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/type/WaterBlock.java diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index e7237e8bf..7be1fe15b 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -258,10 +258,10 @@ public class GeyserImpl implements GeyserApi { VersionCheckUtils.checkForOutdatedJava(logger); for (int i = 0; i < BlockRegistries.JAVA_BLOCKS.get().length; i++) { - String cleanIdentifier = BlockRegistries.JAVA_BLOCKS.get(i).getCleanJavaIdentifier(); - String newIdentifier = BlockRegistries.BLOCK_STATES.get(i).block().javaIdentifier(); - if (!cleanIdentifier.equals(newIdentifier)) { - System.out.println("Check block " + BlockRegistries.BLOCK_STATES.get(i).block().javaIdentifier()); + String oldIdentifier = BlockRegistries.JAVA_BLOCKS.get(i).getJavaIdentifier(); + String newIdentifier = BlockRegistries.BLOCK_STATES.get(i).toString(); + if (!oldIdentifier.equals(newIdentifier)) { + System.out.println("Check block " + oldIdentifier + " " + newIdentifier); break; } } 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 ef584c4fd..0fc5627ed 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,14 +25,14 @@ package org.geysermc.geyser.entity.type; -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; -import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.type.FurnaceBlock; 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.player.Hand; import java.util.UUID; @@ -51,7 +51,7 @@ public class FurnaceMinecartEntity extends DefaultBlockMinecartEntity { @Override public void updateDefaultBlockMetadata() { - dirtyMetadata.put(EntityDataTypes.DISPLAY_BLOCK_STATE, session.getBlockMappings().getBedrockBlock(hasFuel ? BlockStateValues.JAVA_FURNACE_LIT_ID : BlockStateValues.JAVA_FURNACE_ID)); + dirtyMetadata.put(EntityDataTypes.DISPLAY_BLOCK_STATE, session.getBlockMappings().getBedrockBlock(FurnaceBlock.state(hasFuel))); dirtyMetadata.put(EntityDataTypes.DISPLAY_OFFSET, 6); } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/SpawnerMinecartEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/SpawnerMinecartEntity.java index 49cfc0081..65dfb800b 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/SpawnerMinecartEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/SpawnerMinecartEntity.java @@ -28,7 +28,7 @@ package org.geysermc.geyser.entity.type; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.EntityDefinition; -import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.type.SpawnerBlock; import org.geysermc.geyser.session.GeyserSession; import java.util.UUID; @@ -41,7 +41,7 @@ public class SpawnerMinecartEntity extends DefaultBlockMinecartEntity { @Override public void updateDefaultBlockMetadata() { - dirtyMetadata.put(EntityDataTypes.DISPLAY_BLOCK_STATE, session.getBlockMappings().getBedrockBlock(BlockStateValues.JAVA_SPAWNER_ID)); + dirtyMetadata.put(EntityDataTypes.DISPLAY_BLOCK_STATE, session.getBlockMappings().getBedrockBlock(SpawnerBlock.state())); dirtyMetadata.put(EntityDataTypes.DISPLAY_OFFSET, 6); } } 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 62ecaa1e9..9894a4ba2 100644 --- a/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java +++ b/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java @@ -136,7 +136,7 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke placeBlockSoundPacket.setIdentifier(":"); session.sendUpstreamPacket(placeBlockSoundPacket); session.setLastBlockPlacePosition(null); - session.setLastBlockPlacedId(null); + session.setLastBlockPlaced(null); } @Override 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 c11505ffb..686fe39ad 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 @@ -36,8 +36,9 @@ 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.level.block.type.Block; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.registry.BlockRegistries; -import org.geysermc.geyser.registry.type.BlockMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.geysermc.geyser.util.BlockUtils; @@ -59,12 +60,14 @@ public class BlockInventoryHolder extends InventoryHolder { private final ContainerType containerType; private final Set validBlocks; - public BlockInventoryHolder(String javaBlockIdentifier, ContainerType containerType, String... validBlocks) { + public BlockInventoryHolder(String javaBlockIdentifier, ContainerType containerType, Block... validBlocks) { this.defaultJavaBlockState = BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getInt(javaBlockIdentifier); this.containerType = containerType; if (validBlocks != null) { Set validBlocksTemp = new HashSet<>(validBlocks.length + 1); - Collections.addAll(validBlocksTemp, validBlocks); + for (Block block : validBlocks) { + validBlocksTemp.add(block.javaIdentifier().toString()); + } validBlocksTemp.add(BlockUtils.getCleanIdentifier(javaBlockIdentifier)); this.validBlocks = Set.copyOf(validBlocksTemp); } else { @@ -80,14 +83,15 @@ public class BlockInventoryHolder extends InventoryHolder { 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()); - if (!BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get().containsKey(javaBlockId)) { - String[] javaBlockString = BlockRegistries.JAVA_BLOCKS.getOrDefault(javaBlockId, BlockMapping.DEFAULT).getJavaIdentifier().split("\\["); + BlockState state = session.getGeyser().getWorldManager().blockAt(session, session.getLastInteractionBlockPosition()); + if (!BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get().containsKey(state.javaId())) { + // TODO TODO TODO + String[] javaBlockString = state.toString().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); + setCustomName(session, session.getLastInteractionBlockPosition(), inventory, state); return true; } @@ -107,7 +111,7 @@ public class BlockInventoryHolder extends InventoryHolder { session.sendUpstreamPacket(blockPacket); inventory.setHolderPosition(position); - setCustomName(session, position, inventory, defaultJavaBlockState); + setCustomName(session, position, inventory, BlockState.of(defaultJavaBlockState)); return true; } @@ -129,7 +133,7 @@ public class BlockInventoryHolder extends InventoryHolder { return this.validBlocks.contains(javaBlockString[0]); } - protected void setCustomName(GeyserSession session, Vector3i position, Inventory inventory, int javaBlockState) { + protected void setCustomName(GeyserSession session, Vector3i position, Inventory inventory, BlockState javaBlockState) { NbtMap tag = NbtMap.builder() .putInt("x", position.getX()) .putInt("y", position.getY()) 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 f13330700..8c271a7bb 100644 --- a/core/src/main/java/org/geysermc/geyser/item/Items.java +++ b/core/src/main/java/org/geysermc/geyser/item/Items.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.item; import org.geysermc.geyser.item.components.ToolTier; import org.geysermc.geyser.item.type.*; +import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.registry.Registries; import java.util.Collections; @@ -39,770 +40,770 @@ import static org.geysermc.geyser.item.type.Item.builder; @SuppressWarnings("unused") public final class Items { public static final Item AIR = register(new Item("air", builder())); - public static final Item STONE = register(new BlockItem("stone", builder())); - public static final Item GRANITE = register(new BlockItem("granite", builder())); - public static final Item POLISHED_GRANITE = register(new BlockItem("polished_granite", builder())); - public static final Item DIORITE = register(new BlockItem("diorite", builder())); - public static final Item POLISHED_DIORITE = register(new BlockItem("polished_diorite", builder())); - public static final Item ANDESITE = register(new BlockItem("andesite", builder())); - public static final Item POLISHED_ANDESITE = register(new BlockItem("polished_andesite", builder())); - public static final Item DEEPSLATE = register(new BlockItem("deepslate", builder())); - public static final Item COBBLED_DEEPSLATE = register(new BlockItem("cobbled_deepslate", builder())); - 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())); - public static final Item COARSE_DIRT = register(new BlockItem("coarse_dirt", builder())); - public static final Item PODZOL = register(new BlockItem("podzol", builder())); - public static final Item ROOTED_DIRT = register(new BlockItem("rooted_dirt", builder())); - public static final Item MUD = register(new BlockItem("mud", builder())); - public static final Item CRIMSON_NYLIUM = register(new BlockItem("crimson_nylium", builder())); - public static final Item WARPED_NYLIUM = register(new BlockItem("warped_nylium", builder())); - public static final Item COBBLESTONE = register(new BlockItem("cobblestone", builder())); - public static final Item OAK_PLANKS = register(new BlockItem("oak_planks", builder())); - public static final Item SPRUCE_PLANKS = register(new BlockItem("spruce_planks", builder())); - public static final Item BIRCH_PLANKS = register(new BlockItem("birch_planks", builder())); - public static final Item JUNGLE_PLANKS = register(new BlockItem("jungle_planks", builder())); - public static final Item ACACIA_PLANKS = register(new BlockItem("acacia_planks", builder())); - public static final Item CHERRY_PLANKS = register(new BlockItem("cherry_planks", builder())); - public static final Item DARK_OAK_PLANKS = register(new BlockItem("dark_oak_planks", builder())); - public static final Item MANGROVE_PLANKS = register(new BlockItem("mangrove_planks", builder())); - public static final Item BAMBOO_PLANKS = register(new BlockItem("bamboo_planks", builder())); - public static final Item CRIMSON_PLANKS = register(new BlockItem("crimson_planks", builder())); - public static final Item WARPED_PLANKS = register(new BlockItem("warped_planks", builder())); - public static final Item BAMBOO_MOSAIC = register(new BlockItem("bamboo_mosaic", builder())); - public static final Item OAK_SAPLING = register(new BlockItem("oak_sapling", builder())); - public static final Item SPRUCE_SAPLING = register(new BlockItem("spruce_sapling", builder())); - public static final Item BIRCH_SAPLING = register(new BlockItem("birch_sapling", builder())); - public static final Item JUNGLE_SAPLING = register(new BlockItem("jungle_sapling", builder())); - public static final Item ACACIA_SAPLING = register(new BlockItem("acacia_sapling", builder())); - public static final Item CHERRY_SAPLING = register(new BlockItem("cherry_sapling", builder())); - public static final Item DARK_OAK_SAPLING = register(new BlockItem("dark_oak_sapling", builder())); - public static final Item MANGROVE_PROPAGULE = register(new BlockItem("mangrove_propagule", builder())); - public static final Item BEDROCK = register(new BlockItem("bedrock", builder())); - public static final Item SAND = register(new BlockItem("sand", builder())); - public static final Item SUSPICIOUS_SAND = register(new BlockItem("suspicious_sand", builder())); - public static final Item SUSPICIOUS_GRAVEL = register(new BlockItem("suspicious_gravel", builder())); - public static final Item RED_SAND = register(new BlockItem("red_sand", builder())); - public static final Item GRAVEL = register(new BlockItem("gravel", builder())); - public static final Item COAL_ORE = register(new BlockItem("coal_ore", builder())); - public static final Item DEEPSLATE_COAL_ORE = register(new BlockItem("deepslate_coal_ore", builder())); - public static final Item IRON_ORE = register(new BlockItem("iron_ore", builder())); - public static final Item DEEPSLATE_IRON_ORE = register(new BlockItem("deepslate_iron_ore", builder())); - public static final Item COPPER_ORE = register(new BlockItem("copper_ore", builder())); - public static final Item DEEPSLATE_COPPER_ORE = register(new BlockItem("deepslate_copper_ore", builder())); - public static final Item GOLD_ORE = register(new BlockItem("gold_ore", builder())); - public static final Item DEEPSLATE_GOLD_ORE = register(new BlockItem("deepslate_gold_ore", builder())); - public static final Item REDSTONE_ORE = register(new BlockItem("redstone_ore", builder())); - public static final Item DEEPSLATE_REDSTONE_ORE = register(new BlockItem("deepslate_redstone_ore", builder())); - public static final Item EMERALD_ORE = register(new BlockItem("emerald_ore", builder())); - public static final Item DEEPSLATE_EMERALD_ORE = register(new BlockItem("deepslate_emerald_ore", builder())); - public static final Item LAPIS_ORE = register(new BlockItem("lapis_ore", builder())); - public static final Item DEEPSLATE_LAPIS_ORE = register(new BlockItem("deepslate_lapis_ore", builder())); - public static final Item DIAMOND_ORE = register(new BlockItem("diamond_ore", builder())); - public static final Item DEEPSLATE_DIAMOND_ORE = register(new BlockItem("deepslate_diamond_ore", builder())); - public static final Item NETHER_GOLD_ORE = register(new BlockItem("nether_gold_ore", builder())); - public static final Item NETHER_QUARTZ_ORE = register(new BlockItem("nether_quartz_ore", builder())); - public static final Item ANCIENT_DEBRIS = register(new BlockItem("ancient_debris", builder())); - public static final Item COAL_BLOCK = register(new BlockItem("coal_block", builder())); - 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())); - public static final Item COPPER_BLOCK = register(new BlockItem("copper_block", builder())); - public static final Item GOLD_BLOCK = register(new BlockItem("gold_block", builder())); - public static final Item DIAMOND_BLOCK = register(new BlockItem("diamond_block", builder())); - public static final Item NETHERITE_BLOCK = register(new BlockItem("netherite_block", builder())); - 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())); - public static final Item OXIDIZED_CUT_COPPER = register(new BlockItem("oxidized_cut_copper", builder())); - public static final Item CUT_COPPER_STAIRS = register(new BlockItem("cut_copper_stairs", builder())); - public static final Item EXPOSED_CUT_COPPER_STAIRS = register(new BlockItem("exposed_cut_copper_stairs", builder())); - public static final Item WEATHERED_CUT_COPPER_STAIRS = register(new BlockItem("weathered_cut_copper_stairs", builder())); - public static final Item OXIDIZED_CUT_COPPER_STAIRS = register(new BlockItem("oxidized_cut_copper_stairs", builder())); - public static final Item CUT_COPPER_SLAB = register(new BlockItem("cut_copper_slab", builder())); - public static final Item EXPOSED_CUT_COPPER_SLAB = register(new BlockItem("exposed_cut_copper_slab", builder())); - public static final Item WEATHERED_CUT_COPPER_SLAB = register(new BlockItem("weathered_cut_copper_slab", builder())); - public static final Item OXIDIZED_CUT_COPPER_SLAB = register(new BlockItem("oxidized_cut_copper_slab", builder())); - public static final Item WAXED_COPPER_BLOCK = register(new BlockItem("waxed_copper_block", builder())); - 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())); - public static final Item WAXED_OXIDIZED_CUT_COPPER = register(new BlockItem("waxed_oxidized_cut_copper", builder())); - public static final Item WAXED_CUT_COPPER_STAIRS = register(new BlockItem("waxed_cut_copper_stairs", builder())); - public static final Item WAXED_EXPOSED_CUT_COPPER_STAIRS = register(new BlockItem("waxed_exposed_cut_copper_stairs", builder())); - public static final Item WAXED_WEATHERED_CUT_COPPER_STAIRS = register(new BlockItem("waxed_weathered_cut_copper_stairs", builder())); - public static final Item WAXED_OXIDIZED_CUT_COPPER_STAIRS = register(new BlockItem("waxed_oxidized_cut_copper_stairs", builder())); - public static final Item WAXED_CUT_COPPER_SLAB = register(new BlockItem("waxed_cut_copper_slab", builder())); - public static final Item WAXED_EXPOSED_CUT_COPPER_SLAB = register(new BlockItem("waxed_exposed_cut_copper_slab", builder())); - public static final Item WAXED_WEATHERED_CUT_COPPER_SLAB = register(new BlockItem("waxed_weathered_cut_copper_slab", builder())); - public static final Item WAXED_OXIDIZED_CUT_COPPER_SLAB = register(new BlockItem("waxed_oxidized_cut_copper_slab", builder())); - public static final Item OAK_LOG = register(new BlockItem("oak_log", builder())); - public static final Item SPRUCE_LOG = register(new BlockItem("spruce_log", builder())); - public static final Item BIRCH_LOG = register(new BlockItem("birch_log", builder())); - public static final Item JUNGLE_LOG = register(new BlockItem("jungle_log", builder())); - public static final Item ACACIA_LOG = register(new BlockItem("acacia_log", builder())); - public static final Item CHERRY_LOG = register(new BlockItem("cherry_log", builder())); - public static final Item DARK_OAK_LOG = register(new BlockItem("dark_oak_log", builder())); - public static final Item MANGROVE_LOG = register(new BlockItem("mangrove_log", builder())); - public static final Item MANGROVE_ROOTS = register(new BlockItem("mangrove_roots", builder())); - public static final Item MUDDY_MANGROVE_ROOTS = register(new BlockItem("muddy_mangrove_roots", builder())); - public static final Item CRIMSON_STEM = register(new BlockItem("crimson_stem", builder())); - public static final Item WARPED_STEM = register(new BlockItem("warped_stem", builder())); - public static final Item BAMBOO_BLOCK = register(new BlockItem("bamboo_block", builder())); - public static final Item STRIPPED_OAK_LOG = register(new BlockItem("stripped_oak_log", builder())); - public static final Item STRIPPED_SPRUCE_LOG = register(new BlockItem("stripped_spruce_log", builder())); - public static final Item STRIPPED_BIRCH_LOG = register(new BlockItem("stripped_birch_log", builder())); - public static final Item STRIPPED_JUNGLE_LOG = register(new BlockItem("stripped_jungle_log", builder())); - public static final Item STRIPPED_ACACIA_LOG = register(new BlockItem("stripped_acacia_log", builder())); - public static final Item STRIPPED_CHERRY_LOG = register(new BlockItem("stripped_cherry_log", builder())); - public static final Item STRIPPED_DARK_OAK_LOG = register(new BlockItem("stripped_dark_oak_log", builder())); - public static final Item STRIPPED_MANGROVE_LOG = register(new BlockItem("stripped_mangrove_log", builder())); - public static final Item STRIPPED_CRIMSON_STEM = register(new BlockItem("stripped_crimson_stem", builder())); - public static final Item STRIPPED_WARPED_STEM = register(new BlockItem("stripped_warped_stem", builder())); - public static final Item STRIPPED_OAK_WOOD = register(new BlockItem("stripped_oak_wood", builder())); - public static final Item STRIPPED_SPRUCE_WOOD = register(new BlockItem("stripped_spruce_wood", builder())); - public static final Item STRIPPED_BIRCH_WOOD = register(new BlockItem("stripped_birch_wood", builder())); - public static final Item STRIPPED_JUNGLE_WOOD = register(new BlockItem("stripped_jungle_wood", builder())); - public static final Item STRIPPED_ACACIA_WOOD = register(new BlockItem("stripped_acacia_wood", builder())); - public static final Item STRIPPED_CHERRY_WOOD = register(new BlockItem("stripped_cherry_wood", builder())); - public static final Item STRIPPED_DARK_OAK_WOOD = register(new BlockItem("stripped_dark_oak_wood", builder())); - public static final Item STRIPPED_MANGROVE_WOOD = register(new BlockItem("stripped_mangrove_wood", builder())); - public static final Item STRIPPED_CRIMSON_HYPHAE = register(new BlockItem("stripped_crimson_hyphae", builder())); - public static final Item STRIPPED_WARPED_HYPHAE = register(new BlockItem("stripped_warped_hyphae", builder())); - public static final Item STRIPPED_BAMBOO_BLOCK = register(new BlockItem("stripped_bamboo_block", builder())); - public static final Item OAK_WOOD = register(new BlockItem("oak_wood", builder())); - public static final Item SPRUCE_WOOD = register(new BlockItem("spruce_wood", builder())); - public static final Item BIRCH_WOOD = register(new BlockItem("birch_wood", builder())); - public static final Item JUNGLE_WOOD = register(new BlockItem("jungle_wood", builder())); - public static final Item ACACIA_WOOD = register(new BlockItem("acacia_wood", builder())); - public static final Item CHERRY_WOOD = register(new BlockItem("cherry_wood", builder())); - public static final Item DARK_OAK_WOOD = register(new BlockItem("dark_oak_wood", builder())); - public static final Item MANGROVE_WOOD = register(new BlockItem("mangrove_wood", builder())); - public static final Item CRIMSON_HYPHAE = register(new BlockItem("crimson_hyphae", builder())); - public static final Item WARPED_HYPHAE = register(new BlockItem("warped_hyphae", builder())); - public static final Item OAK_LEAVES = register(new BlockItem("oak_leaves", builder())); - public static final Item SPRUCE_LEAVES = register(new BlockItem("spruce_leaves", builder())); - public static final Item BIRCH_LEAVES = register(new BlockItem("birch_leaves", builder())); - public static final Item JUNGLE_LEAVES = register(new BlockItem("jungle_leaves", builder())); - public static final Item ACACIA_LEAVES = register(new BlockItem("acacia_leaves", builder())); - public static final Item CHERRY_LEAVES = register(new BlockItem("cherry_leaves", builder())); - public static final Item DARK_OAK_LEAVES = register(new BlockItem("dark_oak_leaves", builder())); - public static final Item MANGROVE_LEAVES = register(new BlockItem("mangrove_leaves", builder())); - public static final Item AZALEA_LEAVES = register(new BlockItem("azalea_leaves", builder())); - public static final Item FLOWERING_AZALEA_LEAVES = register(new BlockItem("flowering_azalea_leaves", builder())); - public static final Item SPONGE = register(new BlockItem("sponge", builder())); - public static final Item WET_SPONGE = register(new BlockItem("wet_sponge", builder())); - public static final Item GLASS = register(new BlockItem("glass", builder())); - public static final Item TINTED_GLASS = register(new BlockItem("tinted_glass", builder())); - public static final Item LAPIS_BLOCK = register(new BlockItem("lapis_block", builder())); - public static final Item SANDSTONE = register(new BlockItem("sandstone", builder())); - 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 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())); - public static final Item DEAD_BUSH = register(new BlockItem("dead_bush", builder())); - public static final Item SEAGRASS = register(new BlockItem("seagrass", builder())); - public static final Item SEA_PICKLE = register(new BlockItem("sea_pickle", builder())); - public static final Item WHITE_WOOL = register(new BlockItem("white_wool", builder())); - public static final Item ORANGE_WOOL = register(new BlockItem("orange_wool", builder())); - public static final Item MAGENTA_WOOL = register(new BlockItem("magenta_wool", builder())); - public static final Item LIGHT_BLUE_WOOL = register(new BlockItem("light_blue_wool", builder())); - public static final Item YELLOW_WOOL = register(new BlockItem("yellow_wool", builder())); - public static final Item LIME_WOOL = register(new BlockItem("lime_wool", builder())); - public static final Item PINK_WOOL = register(new BlockItem("pink_wool", builder())); - public static final Item GRAY_WOOL = register(new BlockItem("gray_wool", builder())); - public static final Item LIGHT_GRAY_WOOL = register(new BlockItem("light_gray_wool", builder())); - public static final Item CYAN_WOOL = register(new BlockItem("cyan_wool", builder())); - public static final Item PURPLE_WOOL = register(new BlockItem("purple_wool", builder())); - public static final Item BLUE_WOOL = register(new BlockItem("blue_wool", builder())); - public static final Item BROWN_WOOL = register(new BlockItem("brown_wool", builder())); - 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 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())); - public static final Item RED_MUSHROOM = register(new BlockItem("red_mushroom", builder())); - public static final Item CRIMSON_FUNGUS = register(new BlockItem("crimson_fungus", builder())); - public static final Item WARPED_FUNGUS = register(new BlockItem("warped_fungus", builder())); - public static final Item CRIMSON_ROOTS = register(new BlockItem("crimson_roots", builder())); - public static final Item WARPED_ROOTS = register(new BlockItem("warped_roots", builder())); - public static final Item NETHER_SPROUTS = register(new BlockItem("nether_sprouts", builder())); - public static final Item WEEPING_VINES = register(new BlockItem("weeping_vines", builder())); - public static final Item TWISTING_VINES = register(new BlockItem("twisting_vines", builder())); - public static final Item SUGAR_CANE = register(new BlockItem("sugar_cane", builder())); - public static final Item KELP = register(new BlockItem("kelp", builder())); - public static final Item MOSS_CARPET = register(new BlockItem("moss_carpet", builder())); - public static final Item PINK_PETALS = register(new BlockItem("pink_petals", builder())); - public static final Item MOSS_BLOCK = register(new BlockItem("moss_block", builder())); - public static final Item HANGING_ROOTS = register(new BlockItem("hanging_roots", builder())); - public static final Item BIG_DRIPLEAF = register(new BlockItem("big_dripleaf", builder())); - public static final Item SMALL_DRIPLEAF = register(new BlockItem("small_dripleaf", builder())); - public static final Item BAMBOO = register(new BlockItem("bamboo", builder())); - public static final Item OAK_SLAB = register(new BlockItem("oak_slab", builder())); - public static final Item SPRUCE_SLAB = register(new BlockItem("spruce_slab", builder())); - public static final Item BIRCH_SLAB = register(new BlockItem("birch_slab", builder())); - public static final Item JUNGLE_SLAB = register(new BlockItem("jungle_slab", builder())); - public static final Item ACACIA_SLAB = register(new BlockItem("acacia_slab", builder())); - public static final Item CHERRY_SLAB = register(new BlockItem("cherry_slab", builder())); - public static final Item DARK_OAK_SLAB = register(new BlockItem("dark_oak_slab", builder())); - public static final Item MANGROVE_SLAB = register(new BlockItem("mangrove_slab", builder())); - public static final Item BAMBOO_SLAB = register(new BlockItem("bamboo_slab", builder())); - public static final Item BAMBOO_MOSAIC_SLAB = register(new BlockItem("bamboo_mosaic_slab", builder())); - public static final Item CRIMSON_SLAB = register(new BlockItem("crimson_slab", builder())); - public static final Item WARPED_SLAB = register(new BlockItem("warped_slab", builder())); - public static final Item STONE_SLAB = register(new BlockItem("stone_slab", builder())); - public static final Item SMOOTH_STONE_SLAB = register(new BlockItem("smooth_stone_slab", builder())); - public static final Item SANDSTONE_SLAB = register(new BlockItem("sandstone_slab", builder())); - public static final Item CUT_SANDSTONE_SLAB = register(new BlockItem("cut_sandstone_slab", builder())); - public static final Item PETRIFIED_OAK_SLAB = register(new BlockItem("petrified_oak_slab", builder())); - public static final Item COBBLESTONE_SLAB = register(new BlockItem("cobblestone_slab", builder())); - public static final Item BRICK_SLAB = register(new BlockItem("brick_slab", builder())); - public static final Item STONE_BRICK_SLAB = register(new BlockItem("stone_brick_slab", builder())); - public static final Item MUD_BRICK_SLAB = register(new BlockItem("mud_brick_slab", builder())); - public static final Item NETHER_BRICK_SLAB = register(new BlockItem("nether_brick_slab", builder())); - public static final Item QUARTZ_SLAB = register(new BlockItem("quartz_slab", builder())); - public static final Item RED_SANDSTONE_SLAB = register(new BlockItem("red_sandstone_slab", builder())); - public static final Item CUT_RED_SANDSTONE_SLAB = register(new BlockItem("cut_red_sandstone_slab", builder())); - public static final Item PURPUR_SLAB = register(new BlockItem("purpur_slab", builder())); - public static final Item PRISMARINE_SLAB = register(new BlockItem("prismarine_slab", builder())); - public static final Item PRISMARINE_BRICK_SLAB = register(new BlockItem("prismarine_brick_slab", builder())); - public static final Item DARK_PRISMARINE_SLAB = register(new BlockItem("dark_prismarine_slab", builder())); - public static final Item SMOOTH_QUARTZ = register(new BlockItem("smooth_quartz", builder())); - public static final Item SMOOTH_RED_SANDSTONE = register(new BlockItem("smooth_red_sandstone", builder())); - public static final Item SMOOTH_SANDSTONE = register(new BlockItem("smooth_sandstone", builder())); - public static final Item SMOOTH_STONE = register(new BlockItem("smooth_stone", builder())); - 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())); - 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())); - public static final Item END_ROD = register(new BlockItem("end_rod", builder())); - public static final Item CHORUS_PLANT = register(new BlockItem("chorus_plant", builder())); - public static final Item CHORUS_FLOWER = register(new BlockItem("chorus_flower", builder())); - public static final Item PURPUR_BLOCK = register(new BlockItem("purpur_block", builder())); - 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 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())); - public static final Item LADDER = register(new BlockItem("ladder", builder())); - public static final Item COBBLESTONE_STAIRS = register(new BlockItem("cobblestone_stairs", builder())); - public static final Item SNOW = register(new BlockItem("snow", builder())); - public static final Item ICE = register(new BlockItem("ice", builder())); - public static final Item SNOW_BLOCK = register(new BlockItem("snow_block", builder())); - public static final Item CACTUS = register(new BlockItem("cactus", builder())); - public static final Item CLAY = register(new BlockItem("clay", builder())); - public static final Item JUKEBOX = register(new BlockItem("jukebox", builder())); - public static final Item OAK_FENCE = register(new BlockItem("oak_fence", builder())); - public static final Item SPRUCE_FENCE = register(new BlockItem("spruce_fence", builder())); - public static final Item BIRCH_FENCE = register(new BlockItem("birch_fence", builder())); - public static final Item JUNGLE_FENCE = register(new BlockItem("jungle_fence", builder())); - public static final Item ACACIA_FENCE = register(new BlockItem("acacia_fence", builder())); - public static final Item CHERRY_FENCE = register(new BlockItem("cherry_fence", builder())); - public static final Item DARK_OAK_FENCE = register(new BlockItem("dark_oak_fence", builder())); - public static final Item MANGROVE_FENCE = register(new BlockItem("mangrove_fence", builder())); - public static final Item BAMBOO_FENCE = register(new BlockItem("bamboo_fence", builder())); - public static final Item CRIMSON_FENCE = register(new BlockItem("crimson_fence", builder())); - public static final Item WARPED_FENCE = register(new BlockItem("warped_fence", builder())); - public static final Item PUMPKIN = register(new BlockItem("pumpkin", builder())); - public static final Item CARVED_PUMPKIN = register(new BlockItem("carved_pumpkin", builder())); - public static final Item JACK_O_LANTERN = register(new BlockItem("jack_o_lantern", builder())); - public static final Item NETHERRACK = register(new BlockItem("netherrack", builder())); - public static final Item SOUL_SAND = register(new BlockItem("soul_sand", builder())); - public static final Item SOUL_SOIL = register(new BlockItem("soul_soil", builder())); - public static final Item BASALT = register(new BlockItem("basalt", builder())); - public static final Item POLISHED_BASALT = register(new BlockItem("polished_basalt", builder())); - public static final Item SMOOTH_BASALT = register(new BlockItem("smooth_basalt", builder())); - public static final Item SOUL_TORCH = register(new BlockItem("soul_torch", builder())); - public static final Item GLOWSTONE = register(new BlockItem("glowstone", builder())); - public static final Item INFESTED_STONE = register(new BlockItem("infested_stone", builder())); - public static final Item INFESTED_COBBLESTONE = register(new BlockItem("infested_cobblestone", builder())); - public static final Item INFESTED_STONE_BRICKS = register(new BlockItem("infested_stone_bricks", builder())); - public static final Item INFESTED_MOSSY_STONE_BRICKS = register(new BlockItem("infested_mossy_stone_bricks", builder())); - public static final Item INFESTED_CRACKED_STONE_BRICKS = register(new BlockItem("infested_cracked_stone_bricks", builder())); - public static final Item INFESTED_CHISELED_STONE_BRICKS = register(new BlockItem("infested_chiseled_stone_bricks", builder())); - public static final Item INFESTED_DEEPSLATE = register(new BlockItem("infested_deepslate", builder())); - public static final Item STONE_BRICKS = register(new BlockItem("stone_bricks", builder())); - public static final Item MOSSY_STONE_BRICKS = register(new BlockItem("mossy_stone_bricks", builder())); - public static final Item CRACKED_STONE_BRICKS = register(new BlockItem("cracked_stone_bricks", builder())); - public static final Item CHISELED_STONE_BRICKS = register(new BlockItem("chiseled_stone_bricks", builder())); - public static final Item PACKED_MUD = register(new BlockItem("packed_mud", builder())); - public static final Item MUD_BRICKS = register(new BlockItem("mud_bricks", builder())); - public static final Item DEEPSLATE_BRICKS = register(new BlockItem("deepslate_bricks", builder())); - public static final Item CRACKED_DEEPSLATE_BRICKS = register(new BlockItem("cracked_deepslate_bricks", builder())); - public static final Item DEEPSLATE_TILES = register(new BlockItem("deepslate_tiles", builder())); - public static final Item CRACKED_DEEPSLATE_TILES = register(new BlockItem("cracked_deepslate_tiles", builder())); - public static final Item CHISELED_DEEPSLATE = register(new BlockItem("chiseled_deepslate", builder())); - public static final Item REINFORCED_DEEPSLATE = register(new BlockItem("reinforced_deepslate", builder())); - public static final Item BROWN_MUSHROOM_BLOCK = register(new BlockItem("brown_mushroom_block", builder())); - public static final Item RED_MUSHROOM_BLOCK = register(new BlockItem("red_mushroom_block", builder())); - public static final Item MUSHROOM_STEM = register(new BlockItem("mushroom_stem", builder())); - public static final Item IRON_BARS = register(new BlockItem("iron_bars", builder())); - public static final Item CHAIN = register(new BlockItem("chain", builder())); - public static final Item GLASS_PANE = register(new BlockItem("glass_pane", builder())); - public static final Item MELON = register(new BlockItem("melon", builder())); - public static final Item VINE = register(new BlockItem("vine", builder())); - public static final Item GLOW_LICHEN = register(new BlockItem("glow_lichen", builder())); - public static final Item BRICK_STAIRS = register(new BlockItem("brick_stairs", builder())); - public static final Item STONE_BRICK_STAIRS = register(new BlockItem("stone_brick_stairs", builder())); - public static final Item MUD_BRICK_STAIRS = register(new BlockItem("mud_brick_stairs", builder())); - public static final Item MYCELIUM = register(new BlockItem("mycelium", builder())); - public static final Item LILY_PAD = register(new BlockItem("lily_pad", builder())); - public static final Item NETHER_BRICKS = register(new BlockItem("nether_bricks", builder())); - public static final Item CRACKED_NETHER_BRICKS = register(new BlockItem("cracked_nether_bricks", builder())); - public static final Item CHISELED_NETHER_BRICKS = register(new BlockItem("chiseled_nether_bricks", builder())); - public static final Item NETHER_BRICK_FENCE = register(new BlockItem("nether_brick_fence", builder())); - public static final Item NETHER_BRICK_STAIRS = register(new BlockItem("nether_brick_stairs", builder())); - public static final Item SCULK = register(new BlockItem("sculk", builder())); - public static final Item SCULK_VEIN = register(new BlockItem("sculk_vein", builder())); - public static final Item SCULK_CATALYST = register(new BlockItem("sculk_catalyst", builder())); - public static final Item SCULK_SHRIEKER = register(new BlockItem("sculk_shrieker", builder())); - public static final Item ENCHANTING_TABLE = register(new BlockItem("enchanting_table", builder())); - public static final Item END_PORTAL_FRAME = register(new BlockItem("end_portal_frame", builder())); - public static final Item END_STONE = register(new BlockItem("end_stone", builder())); - 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 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())); - public static final Item BIRCH_STAIRS = register(new BlockItem("birch_stairs", builder())); - public static final Item JUNGLE_STAIRS = register(new BlockItem("jungle_stairs", builder())); - public static final Item ACACIA_STAIRS = register(new BlockItem("acacia_stairs", builder())); - public static final Item CHERRY_STAIRS = register(new BlockItem("cherry_stairs", builder())); - public static final Item DARK_OAK_STAIRS = register(new BlockItem("dark_oak_stairs", builder())); - public static final Item MANGROVE_STAIRS = register(new BlockItem("mangrove_stairs", builder())); - public static final Item BAMBOO_STAIRS = register(new BlockItem("bamboo_stairs", builder())); - public static final Item BAMBOO_MOSAIC_STAIRS = register(new BlockItem("bamboo_mosaic_stairs", builder())); - public static final Item CRIMSON_STAIRS = register(new BlockItem("crimson_stairs", builder())); - public static final Item WARPED_STAIRS = register(new BlockItem("warped_stairs", builder())); - public static final Item COMMAND_BLOCK = register(new BlockItem("command_block", builder())); - public static final Item BEACON = register(new BlockItem("beacon", builder())); - public static final Item COBBLESTONE_WALL = register(new BlockItem("cobblestone_wall", builder())); - public static final Item MOSSY_COBBLESTONE_WALL = register(new BlockItem("mossy_cobblestone_wall", builder())); - public static final Item BRICK_WALL = register(new BlockItem("brick_wall", builder())); - public static final Item PRISMARINE_WALL = register(new BlockItem("prismarine_wall", builder())); - public static final Item RED_SANDSTONE_WALL = register(new BlockItem("red_sandstone_wall", builder())); - public static final Item MOSSY_STONE_BRICK_WALL = register(new BlockItem("mossy_stone_brick_wall", builder())); - public static final Item GRANITE_WALL = register(new BlockItem("granite_wall", builder())); - public static final Item STONE_BRICK_WALL = register(new BlockItem("stone_brick_wall", builder())); - public static final Item MUD_BRICK_WALL = register(new BlockItem("mud_brick_wall", builder())); - public static final Item NETHER_BRICK_WALL = register(new BlockItem("nether_brick_wall", builder())); - public static final Item ANDESITE_WALL = register(new BlockItem("andesite_wall", builder())); - public static final Item RED_NETHER_BRICK_WALL = register(new BlockItem("red_nether_brick_wall", builder())); - public static final Item SANDSTONE_WALL = register(new BlockItem("sandstone_wall", builder())); - public static final Item END_STONE_BRICK_WALL = register(new BlockItem("end_stone_brick_wall", builder())); - public static final Item DIORITE_WALL = register(new BlockItem("diorite_wall", builder())); - public static final Item BLACKSTONE_WALL = register(new BlockItem("blackstone_wall", builder())); - public static final Item POLISHED_BLACKSTONE_WALL = register(new BlockItem("polished_blackstone_wall", builder())); - public static final Item POLISHED_BLACKSTONE_BRICK_WALL = register(new BlockItem("polished_blackstone_brick_wall", builder())); - public static final Item COBBLED_DEEPSLATE_WALL = register(new BlockItem("cobbled_deepslate_wall", builder())); - public static final Item POLISHED_DEEPSLATE_WALL = register(new BlockItem("polished_deepslate_wall", builder())); - public static final Item DEEPSLATE_BRICK_WALL = register(new BlockItem("deepslate_brick_wall", builder())); - public static final Item DEEPSLATE_TILE_WALL = register(new BlockItem("deepslate_tile_wall", builder())); - public static final Item ANVIL = register(new BlockItem("anvil", builder())); - public static final Item CHIPPED_ANVIL = register(new BlockItem("chipped_anvil", builder())); - public static final Item DAMAGED_ANVIL = register(new BlockItem("damaged_anvil", builder())); - public static final Item CHISELED_QUARTZ_BLOCK = register(new BlockItem("chiseled_quartz_block", builder())); - public static final Item QUARTZ_BLOCK = register(new BlockItem("quartz_block", builder())); - public static final Item QUARTZ_BRICKS = register(new BlockItem("quartz_bricks", builder())); - public static final Item QUARTZ_PILLAR = register(new BlockItem("quartz_pillar", builder())); - public static final Item QUARTZ_STAIRS = register(new BlockItem("quartz_stairs", builder())); - public static final Item WHITE_TERRACOTTA = register(new BlockItem("white_terracotta", builder())); - public static final Item ORANGE_TERRACOTTA = register(new BlockItem("orange_terracotta", builder())); - public static final Item MAGENTA_TERRACOTTA = register(new BlockItem("magenta_terracotta", builder())); - public static final Item LIGHT_BLUE_TERRACOTTA = register(new BlockItem("light_blue_terracotta", builder())); - public static final Item YELLOW_TERRACOTTA = register(new BlockItem("yellow_terracotta", builder())); - public static final Item LIME_TERRACOTTA = register(new BlockItem("lime_terracotta", builder())); - public static final Item PINK_TERRACOTTA = register(new BlockItem("pink_terracotta", builder())); - public static final Item GRAY_TERRACOTTA = register(new BlockItem("gray_terracotta", builder())); - public static final Item LIGHT_GRAY_TERRACOTTA = register(new BlockItem("light_gray_terracotta", builder())); - public static final Item CYAN_TERRACOTTA = register(new BlockItem("cyan_terracotta", builder())); - public static final Item PURPLE_TERRACOTTA = register(new BlockItem("purple_terracotta", builder())); - public static final Item BLUE_TERRACOTTA = register(new BlockItem("blue_terracotta", builder())); - public static final Item BROWN_TERRACOTTA = register(new BlockItem("brown_terracotta", builder())); - public static final Item GREEN_TERRACOTTA = register(new BlockItem("green_terracotta", builder())); - public static final Item RED_TERRACOTTA = register(new BlockItem("red_terracotta", builder())); - public static final Item BLACK_TERRACOTTA = register(new BlockItem("black_terracotta", builder())); - public static final Item BARRIER = register(new BlockItem("barrier", builder())); - public static final Item LIGHT = register(new BlockItem("light", builder())); - public static final Item HAY_BLOCK = register(new BlockItem("hay_block", builder())); - public static final Item WHITE_CARPET = register(new BlockItem("white_carpet", builder())); - public static final Item ORANGE_CARPET = register(new BlockItem("orange_carpet", builder())); - public static final Item MAGENTA_CARPET = register(new BlockItem("magenta_carpet", builder())); - public static final Item LIGHT_BLUE_CARPET = register(new BlockItem("light_blue_carpet", builder())); - public static final Item YELLOW_CARPET = register(new BlockItem("yellow_carpet", builder())); - public static final Item LIME_CARPET = register(new BlockItem("lime_carpet", builder())); - public static final Item PINK_CARPET = register(new BlockItem("pink_carpet", builder())); - public static final Item GRAY_CARPET = register(new BlockItem("gray_carpet", builder())); - public static final Item LIGHT_GRAY_CARPET = register(new BlockItem("light_gray_carpet", builder())); - public static final Item CYAN_CARPET = register(new BlockItem("cyan_carpet", builder())); - public static final Item PURPLE_CARPET = register(new BlockItem("purple_carpet", builder())); - public static final Item BLUE_CARPET = register(new BlockItem("blue_carpet", builder())); - public static final Item BROWN_CARPET = register(new BlockItem("brown_carpet", builder())); - public static final Item GREEN_CARPET = register(new BlockItem("green_carpet", builder())); - public static final Item RED_CARPET = register(new BlockItem("red_carpet", builder())); - public static final Item BLACK_CARPET = register(new BlockItem("black_carpet", builder())); - public static final Item TERRACOTTA = register(new BlockItem("terracotta", builder())); - public static final Item PACKED_ICE = register(new BlockItem("packed_ice", builder())); - public static final Item DIRT_PATH = register(new BlockItem("dirt_path", builder())); - public static final Item SUNFLOWER = register(new BlockItem("sunflower", builder())); - public static final Item LILAC = register(new BlockItem("lilac", builder())); - public static final Item ROSE_BUSH = register(new BlockItem("rose_bush", builder())); - public static final Item PEONY = register(new BlockItem("peony", builder())); - public static final Item TALL_GRASS = register(new BlockItem("tall_grass", builder())); - public static final Item LARGE_FERN = register(new BlockItem("large_fern", builder())); - public static final Item WHITE_STAINED_GLASS = register(new BlockItem("white_stained_glass", builder())); - public static final Item ORANGE_STAINED_GLASS = register(new BlockItem("orange_stained_glass", builder())); - public static final Item MAGENTA_STAINED_GLASS = register(new BlockItem("magenta_stained_glass", builder())); - public static final Item LIGHT_BLUE_STAINED_GLASS = register(new BlockItem("light_blue_stained_glass", builder())); - public static final Item YELLOW_STAINED_GLASS = register(new BlockItem("yellow_stained_glass", builder())); - public static final Item LIME_STAINED_GLASS = register(new BlockItem("lime_stained_glass", builder())); - public static final Item PINK_STAINED_GLASS = register(new BlockItem("pink_stained_glass", builder())); - public static final Item GRAY_STAINED_GLASS = register(new BlockItem("gray_stained_glass", builder())); - public static final Item LIGHT_GRAY_STAINED_GLASS = register(new BlockItem("light_gray_stained_glass", builder())); - public static final Item CYAN_STAINED_GLASS = register(new BlockItem("cyan_stained_glass", builder())); - public static final Item PURPLE_STAINED_GLASS = register(new BlockItem("purple_stained_glass", builder())); - public static final Item BLUE_STAINED_GLASS = register(new BlockItem("blue_stained_glass", builder())); - public static final Item BROWN_STAINED_GLASS = register(new BlockItem("brown_stained_glass", builder())); - public static final Item GREEN_STAINED_GLASS = register(new BlockItem("green_stained_glass", builder())); - public static final Item RED_STAINED_GLASS = register(new BlockItem("red_stained_glass", builder())); - public static final Item BLACK_STAINED_GLASS = register(new BlockItem("black_stained_glass", builder())); - public static final Item WHITE_STAINED_GLASS_PANE = register(new BlockItem("white_stained_glass_pane", builder())); - public static final Item ORANGE_STAINED_GLASS_PANE = register(new BlockItem("orange_stained_glass_pane", builder())); - public static final Item MAGENTA_STAINED_GLASS_PANE = register(new BlockItem("magenta_stained_glass_pane", builder())); - public static final Item LIGHT_BLUE_STAINED_GLASS_PANE = register(new BlockItem("light_blue_stained_glass_pane", builder())); - public static final Item YELLOW_STAINED_GLASS_PANE = register(new BlockItem("yellow_stained_glass_pane", builder())); - public static final Item LIME_STAINED_GLASS_PANE = register(new BlockItem("lime_stained_glass_pane", builder())); - public static final Item PINK_STAINED_GLASS_PANE = register(new BlockItem("pink_stained_glass_pane", builder())); - public static final Item GRAY_STAINED_GLASS_PANE = register(new BlockItem("gray_stained_glass_pane", builder())); - public static final Item LIGHT_GRAY_STAINED_GLASS_PANE = register(new BlockItem("light_gray_stained_glass_pane", builder())); - public static final Item CYAN_STAINED_GLASS_PANE = register(new BlockItem("cyan_stained_glass_pane", builder())); - public static final Item PURPLE_STAINED_GLASS_PANE = register(new BlockItem("purple_stained_glass_pane", builder())); - public static final Item BLUE_STAINED_GLASS_PANE = register(new BlockItem("blue_stained_glass_pane", builder())); - public static final Item BROWN_STAINED_GLASS_PANE = register(new BlockItem("brown_stained_glass_pane", builder())); - public static final Item GREEN_STAINED_GLASS_PANE = register(new BlockItem("green_stained_glass_pane", builder())); - public static final Item RED_STAINED_GLASS_PANE = register(new BlockItem("red_stained_glass_pane", builder())); - public static final Item BLACK_STAINED_GLASS_PANE = register(new BlockItem("black_stained_glass_pane", builder())); - public static final Item PRISMARINE = register(new BlockItem("prismarine", builder())); - public static final Item PRISMARINE_BRICKS = register(new BlockItem("prismarine_bricks", builder())); - public static final Item DARK_PRISMARINE = register(new BlockItem("dark_prismarine", builder())); - public static final Item PRISMARINE_STAIRS = register(new BlockItem("prismarine_stairs", builder())); - public static final Item PRISMARINE_BRICK_STAIRS = register(new BlockItem("prismarine_brick_stairs", builder())); - public static final Item DARK_PRISMARINE_STAIRS = register(new BlockItem("dark_prismarine_stairs", builder())); - public static final Item SEA_LANTERN = register(new BlockItem("sea_lantern", builder())); - public static final Item RED_SANDSTONE = register(new BlockItem("red_sandstone", builder())); - public static final Item CHISELED_RED_SANDSTONE = register(new BlockItem("chiseled_red_sandstone", builder())); - public static final Item CUT_RED_SANDSTONE = register(new BlockItem("cut_red_sandstone", builder())); - public static final Item RED_SANDSTONE_STAIRS = register(new BlockItem("red_sandstone_stairs", builder())); - public static final Item REPEATING_COMMAND_BLOCK = register(new BlockItem("repeating_command_block", builder())); - public static final Item CHAIN_COMMAND_BLOCK = register(new BlockItem("chain_command_block", builder())); - public static final Item MAGMA_BLOCK = register(new BlockItem("magma_block", builder())); - public static final Item NETHER_WART_BLOCK = register(new BlockItem("nether_wart_block", builder())); - public static final Item WARPED_WART_BLOCK = register(new BlockItem("warped_wart_block", builder())); - public static final Item RED_NETHER_BRICKS = register(new BlockItem("red_nether_bricks", builder())); - public static final Item BONE_BLOCK = register(new BlockItem("bone_block", builder())); - public static final Item STRUCTURE_VOID = register(new BlockItem("structure_void", builder())); - public static final Item SHULKER_BOX = register(new ShulkerBoxItem("shulker_box", builder().stackSize(1))); - public static final Item WHITE_SHULKER_BOX = register(new ShulkerBoxItem("white_shulker_box", builder().stackSize(1))); - public static final Item ORANGE_SHULKER_BOX = register(new ShulkerBoxItem("orange_shulker_box", builder().stackSize(1))); - public static final Item MAGENTA_SHULKER_BOX = register(new ShulkerBoxItem("magenta_shulker_box", builder().stackSize(1))); - public static final Item LIGHT_BLUE_SHULKER_BOX = register(new ShulkerBoxItem("light_blue_shulker_box", builder().stackSize(1))); - public static final Item YELLOW_SHULKER_BOX = register(new ShulkerBoxItem("yellow_shulker_box", builder().stackSize(1))); - public static final Item LIME_SHULKER_BOX = register(new ShulkerBoxItem("lime_shulker_box", builder().stackSize(1))); - public static final Item PINK_SHULKER_BOX = register(new ShulkerBoxItem("pink_shulker_box", builder().stackSize(1))); - public static final Item GRAY_SHULKER_BOX = register(new ShulkerBoxItem("gray_shulker_box", builder().stackSize(1))); - public static final Item LIGHT_GRAY_SHULKER_BOX = register(new ShulkerBoxItem("light_gray_shulker_box", builder().stackSize(1))); - public static final Item CYAN_SHULKER_BOX = register(new ShulkerBoxItem("cyan_shulker_box", builder().stackSize(1))); - public static final Item PURPLE_SHULKER_BOX = register(new ShulkerBoxItem("purple_shulker_box", builder().stackSize(1))); - public static final Item BLUE_SHULKER_BOX = register(new ShulkerBoxItem("blue_shulker_box", builder().stackSize(1))); - public static final Item BROWN_SHULKER_BOX = register(new ShulkerBoxItem("brown_shulker_box", builder().stackSize(1))); - public static final Item GREEN_SHULKER_BOX = register(new ShulkerBoxItem("green_shulker_box", builder().stackSize(1))); - public static final Item RED_SHULKER_BOX = register(new ShulkerBoxItem("red_shulker_box", builder().stackSize(1))); - public static final Item BLACK_SHULKER_BOX = register(new ShulkerBoxItem("black_shulker_box", builder().stackSize(1))); - public static final Item WHITE_GLAZED_TERRACOTTA = register(new BlockItem("white_glazed_terracotta", builder())); - public static final Item ORANGE_GLAZED_TERRACOTTA = register(new BlockItem("orange_glazed_terracotta", builder())); - public static final Item MAGENTA_GLAZED_TERRACOTTA = register(new BlockItem("magenta_glazed_terracotta", builder())); - public static final Item LIGHT_BLUE_GLAZED_TERRACOTTA = register(new BlockItem("light_blue_glazed_terracotta", builder())); - public static final Item YELLOW_GLAZED_TERRACOTTA = register(new BlockItem("yellow_glazed_terracotta", builder())); - public static final Item LIME_GLAZED_TERRACOTTA = register(new BlockItem("lime_glazed_terracotta", builder())); - public static final Item PINK_GLAZED_TERRACOTTA = register(new BlockItem("pink_glazed_terracotta", builder())); - public static final Item GRAY_GLAZED_TERRACOTTA = register(new BlockItem("gray_glazed_terracotta", builder())); - public static final Item LIGHT_GRAY_GLAZED_TERRACOTTA = register(new BlockItem("light_gray_glazed_terracotta", builder())); - public static final Item CYAN_GLAZED_TERRACOTTA = register(new BlockItem("cyan_glazed_terracotta", builder())); - public static final Item PURPLE_GLAZED_TERRACOTTA = register(new BlockItem("purple_glazed_terracotta", builder())); - public static final Item BLUE_GLAZED_TERRACOTTA = register(new BlockItem("blue_glazed_terracotta", builder())); - public static final Item BROWN_GLAZED_TERRACOTTA = register(new BlockItem("brown_glazed_terracotta", builder())); - public static final Item GREEN_GLAZED_TERRACOTTA = register(new BlockItem("green_glazed_terracotta", builder())); - public static final Item RED_GLAZED_TERRACOTTA = register(new BlockItem("red_glazed_terracotta", builder())); - public static final Item BLACK_GLAZED_TERRACOTTA = register(new BlockItem("black_glazed_terracotta", builder())); - public static final Item WHITE_CONCRETE = register(new BlockItem("white_concrete", builder())); - public static final Item ORANGE_CONCRETE = register(new BlockItem("orange_concrete", builder())); - public static final Item MAGENTA_CONCRETE = register(new BlockItem("magenta_concrete", builder())); - public static final Item LIGHT_BLUE_CONCRETE = register(new BlockItem("light_blue_concrete", builder())); - public static final Item YELLOW_CONCRETE = register(new BlockItem("yellow_concrete", builder())); - public static final Item LIME_CONCRETE = register(new BlockItem("lime_concrete", builder())); - public static final Item PINK_CONCRETE = register(new BlockItem("pink_concrete", builder())); - public static final Item GRAY_CONCRETE = register(new BlockItem("gray_concrete", builder())); - public static final Item LIGHT_GRAY_CONCRETE = register(new BlockItem("light_gray_concrete", builder())); - public static final Item CYAN_CONCRETE = register(new BlockItem("cyan_concrete", builder())); - public static final Item PURPLE_CONCRETE = register(new BlockItem("purple_concrete", builder())); - public static final Item BLUE_CONCRETE = register(new BlockItem("blue_concrete", builder())); - public static final Item BROWN_CONCRETE = register(new BlockItem("brown_concrete", builder())); - public static final Item GREEN_CONCRETE = register(new BlockItem("green_concrete", builder())); - public static final Item RED_CONCRETE = register(new BlockItem("red_concrete", builder())); - public static final Item BLACK_CONCRETE = register(new BlockItem("black_concrete", builder())); - public static final Item WHITE_CONCRETE_POWDER = register(new BlockItem("white_concrete_powder", builder())); - public static final Item ORANGE_CONCRETE_POWDER = register(new BlockItem("orange_concrete_powder", builder())); - public static final Item MAGENTA_CONCRETE_POWDER = register(new BlockItem("magenta_concrete_powder", builder())); - public static final Item LIGHT_BLUE_CONCRETE_POWDER = register(new BlockItem("light_blue_concrete_powder", builder())); - public static final Item YELLOW_CONCRETE_POWDER = register(new BlockItem("yellow_concrete_powder", builder())); - public static final Item LIME_CONCRETE_POWDER = register(new BlockItem("lime_concrete_powder", builder())); - public static final Item PINK_CONCRETE_POWDER = register(new BlockItem("pink_concrete_powder", builder())); - public static final Item GRAY_CONCRETE_POWDER = register(new BlockItem("gray_concrete_powder", builder())); - public static final Item LIGHT_GRAY_CONCRETE_POWDER = register(new BlockItem("light_gray_concrete_powder", builder())); - public static final Item CYAN_CONCRETE_POWDER = register(new BlockItem("cyan_concrete_powder", builder())); - public static final Item PURPLE_CONCRETE_POWDER = register(new BlockItem("purple_concrete_powder", builder())); - public static final Item BLUE_CONCRETE_POWDER = register(new BlockItem("blue_concrete_powder", builder())); - public static final Item BROWN_CONCRETE_POWDER = register(new BlockItem("brown_concrete_powder", builder())); - public static final Item GREEN_CONCRETE_POWDER = register(new BlockItem("green_concrete_powder", builder())); - public static final Item RED_CONCRETE_POWDER = register(new BlockItem("red_concrete_powder", builder())); - public static final Item BLACK_CONCRETE_POWDER = register(new BlockItem("black_concrete_powder", builder())); - public static final Item TURTLE_EGG = register(new BlockItem("turtle_egg", builder())); - public static final Item SNIFFER_EGG = register(new BlockItem("sniffer_egg", builder())); - public static final Item DEAD_TUBE_CORAL_BLOCK = register(new BlockItem("dead_tube_coral_block", builder())); - public static final Item DEAD_BRAIN_CORAL_BLOCK = register(new BlockItem("dead_brain_coral_block", builder())); - public static final Item DEAD_BUBBLE_CORAL_BLOCK = register(new BlockItem("dead_bubble_coral_block", builder())); - public static final Item DEAD_FIRE_CORAL_BLOCK = register(new BlockItem("dead_fire_coral_block", builder())); - public static final Item DEAD_HORN_CORAL_BLOCK = register(new BlockItem("dead_horn_coral_block", builder())); - public static final Item TUBE_CORAL_BLOCK = register(new BlockItem("tube_coral_block", builder())); - public static final Item BRAIN_CORAL_BLOCK = register(new BlockItem("brain_coral_block", builder())); - public static final Item BUBBLE_CORAL_BLOCK = register(new BlockItem("bubble_coral_block", builder())); - public static final Item FIRE_CORAL_BLOCK = register(new BlockItem("fire_coral_block", builder())); - public static final Item HORN_CORAL_BLOCK = register(new BlockItem("horn_coral_block", builder())); - public static final Item TUBE_CORAL = register(new BlockItem("tube_coral", builder())); - public static final Item BRAIN_CORAL = register(new BlockItem("brain_coral", builder())); - public static final Item BUBBLE_CORAL = register(new BlockItem("bubble_coral", builder())); - public static final Item FIRE_CORAL = register(new BlockItem("fire_coral", builder())); - public static final Item HORN_CORAL = register(new BlockItem("horn_coral", builder())); - public static final Item DEAD_BRAIN_CORAL = register(new BlockItem("dead_brain_coral", builder())); - public static final Item DEAD_BUBBLE_CORAL = register(new BlockItem("dead_bubble_coral", builder())); - public static final Item DEAD_FIRE_CORAL = register(new BlockItem("dead_fire_coral", builder())); - public static final Item DEAD_HORN_CORAL = register(new BlockItem("dead_horn_coral", builder())); - public static final Item DEAD_TUBE_CORAL = register(new BlockItem("dead_tube_coral", builder())); - public static final Item TUBE_CORAL_FAN = register(new BlockItem("tube_coral_fan", builder())); - public static final Item BRAIN_CORAL_FAN = register(new BlockItem("brain_coral_fan", builder())); - public static final Item BUBBLE_CORAL_FAN = register(new BlockItem("bubble_coral_fan", builder())); - public static final Item FIRE_CORAL_FAN = register(new BlockItem("fire_coral_fan", builder())); - public static final Item HORN_CORAL_FAN = register(new BlockItem("horn_coral_fan", builder())); - public static final Item DEAD_TUBE_CORAL_FAN = register(new BlockItem("dead_tube_coral_fan", builder())); - public static final Item DEAD_BRAIN_CORAL_FAN = register(new BlockItem("dead_brain_coral_fan", builder())); - public static final Item DEAD_BUBBLE_CORAL_FAN = register(new BlockItem("dead_bubble_coral_fan", builder())); - public static final Item DEAD_FIRE_CORAL_FAN = register(new BlockItem("dead_fire_coral_fan", builder())); - public static final Item DEAD_HORN_CORAL_FAN = register(new BlockItem("dead_horn_coral_fan", builder())); - public static final Item BLUE_ICE = register(new BlockItem("blue_ice", builder())); - public static final Item CONDUIT = register(new BlockItem("conduit", builder())); - public static final Item POLISHED_GRANITE_STAIRS = register(new BlockItem("polished_granite_stairs", builder())); - public static final Item SMOOTH_RED_SANDSTONE_STAIRS = register(new BlockItem("smooth_red_sandstone_stairs", builder())); - public static final Item MOSSY_STONE_BRICK_STAIRS = register(new BlockItem("mossy_stone_brick_stairs", builder())); - public static final Item POLISHED_DIORITE_STAIRS = register(new BlockItem("polished_diorite_stairs", builder())); - public static final Item MOSSY_COBBLESTONE_STAIRS = register(new BlockItem("mossy_cobblestone_stairs", builder())); - public static final Item END_STONE_BRICK_STAIRS = register(new BlockItem("end_stone_brick_stairs", builder())); - public static final Item STONE_STAIRS = register(new BlockItem("stone_stairs", builder())); - public static final Item SMOOTH_SANDSTONE_STAIRS = register(new BlockItem("smooth_sandstone_stairs", builder())); - public static final Item SMOOTH_QUARTZ_STAIRS = register(new BlockItem("smooth_quartz_stairs", builder())); - public static final Item GRANITE_STAIRS = register(new BlockItem("granite_stairs", builder())); - public static final Item ANDESITE_STAIRS = register(new BlockItem("andesite_stairs", builder())); - public static final Item RED_NETHER_BRICK_STAIRS = register(new BlockItem("red_nether_brick_stairs", builder())); - public static final Item POLISHED_ANDESITE_STAIRS = register(new BlockItem("polished_andesite_stairs", builder())); - public static final Item DIORITE_STAIRS = register(new BlockItem("diorite_stairs", builder())); - public static final Item COBBLED_DEEPSLATE_STAIRS = register(new BlockItem("cobbled_deepslate_stairs", builder())); - public static final Item POLISHED_DEEPSLATE_STAIRS = register(new BlockItem("polished_deepslate_stairs", builder())); - public static final Item DEEPSLATE_BRICK_STAIRS = register(new BlockItem("deepslate_brick_stairs", builder())); - public static final Item DEEPSLATE_TILE_STAIRS = register(new BlockItem("deepslate_tile_stairs", builder())); - public static final Item POLISHED_GRANITE_SLAB = register(new BlockItem("polished_granite_slab", builder())); - public static final Item SMOOTH_RED_SANDSTONE_SLAB = register(new BlockItem("smooth_red_sandstone_slab", builder())); - public static final Item MOSSY_STONE_BRICK_SLAB = register(new BlockItem("mossy_stone_brick_slab", builder())); - public static final Item POLISHED_DIORITE_SLAB = register(new BlockItem("polished_diorite_slab", builder())); - public static final Item MOSSY_COBBLESTONE_SLAB = register(new BlockItem("mossy_cobblestone_slab", builder())); - public static final Item END_STONE_BRICK_SLAB = register(new BlockItem("end_stone_brick_slab", builder())); - public static final Item SMOOTH_SANDSTONE_SLAB = register(new BlockItem("smooth_sandstone_slab", builder())); - public static final Item SMOOTH_QUARTZ_SLAB = register(new BlockItem("smooth_quartz_slab", builder())); - public static final Item GRANITE_SLAB = register(new BlockItem("granite_slab", builder())); - public static final Item ANDESITE_SLAB = register(new BlockItem("andesite_slab", builder())); - public static final Item RED_NETHER_BRICK_SLAB = register(new BlockItem("red_nether_brick_slab", builder())); - public static final Item POLISHED_ANDESITE_SLAB = register(new BlockItem("polished_andesite_slab", builder())); - public static final Item DIORITE_SLAB = register(new BlockItem("diorite_slab", builder())); - public static final Item COBBLED_DEEPSLATE_SLAB = register(new BlockItem("cobbled_deepslate_slab", builder())); - public static final Item POLISHED_DEEPSLATE_SLAB = register(new BlockItem("polished_deepslate_slab", builder())); - public static final Item DEEPSLATE_BRICK_SLAB = register(new BlockItem("deepslate_brick_slab", builder())); - public static final Item DEEPSLATE_TILE_SLAB = register(new BlockItem("deepslate_tile_slab", builder())); - public static final Item SCAFFOLDING = register(new BlockItem("scaffolding", builder())); - public static final Item REDSTONE = register(new BlockItem("redstone", builder())); - public static final Item REDSTONE_TORCH = register(new BlockItem("redstone_torch", builder())); - public static final Item REDSTONE_BLOCK = register(new BlockItem("redstone_block", builder())); - public static final Item REPEATER = register(new BlockItem("repeater", builder())); - public static final Item COMPARATOR = register(new BlockItem("comparator", builder())); - public static final Item PISTON = register(new BlockItem("piston", builder())); - public static final Item STICKY_PISTON = register(new BlockItem("sticky_piston", builder())); - public static final Item SLIME_BLOCK = register(new BlockItem("slime_block", builder())); - public static final Item HONEY_BLOCK = register(new BlockItem("honey_block", builder())); - public static final Item OBSERVER = register(new BlockItem("observer", builder())); - public static final Item HOPPER = register(new BlockItem("hopper", builder())); - public static final Item DISPENSER = register(new BlockItem("dispenser", builder())); - public static final Item DROPPER = register(new BlockItem("dropper", builder())); - public static final Item LECTERN = register(new BlockItem("lectern", builder())); - public static final Item TARGET = register(new BlockItem("target", builder())); - public static final Item LEVER = register(new BlockItem("lever", builder())); - public static final Item LIGHTNING_ROD = register(new BlockItem("lightning_rod", builder())); - public static final Item DAYLIGHT_DETECTOR = register(new BlockItem("daylight_detector", builder())); - 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 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())); - public static final Item STONE_BUTTON = register(new BlockItem("stone_button", builder())); - public static final Item POLISHED_BLACKSTONE_BUTTON = register(new BlockItem("polished_blackstone_button", builder())); - public static final Item OAK_BUTTON = register(new BlockItem("oak_button", builder())); - public static final Item SPRUCE_BUTTON = register(new BlockItem("spruce_button", builder())); - public static final Item BIRCH_BUTTON = register(new BlockItem("birch_button", builder())); - public static final Item JUNGLE_BUTTON = register(new BlockItem("jungle_button", builder())); - public static final Item ACACIA_BUTTON = register(new BlockItem("acacia_button", builder())); - public static final Item CHERRY_BUTTON = register(new BlockItem("cherry_button", builder())); - public static final Item DARK_OAK_BUTTON = register(new BlockItem("dark_oak_button", builder())); - public static final Item MANGROVE_BUTTON = register(new BlockItem("mangrove_button", builder())); - public static final Item BAMBOO_BUTTON = register(new BlockItem("bamboo_button", builder())); - public static final Item CRIMSON_BUTTON = register(new BlockItem("crimson_button", builder())); - public static final Item WARPED_BUTTON = register(new BlockItem("warped_button", builder())); - public static final Item STONE_PRESSURE_PLATE = register(new BlockItem("stone_pressure_plate", builder())); - public static final Item POLISHED_BLACKSTONE_PRESSURE_PLATE = register(new BlockItem("polished_blackstone_pressure_plate", builder())); - public static final Item LIGHT_WEIGHTED_PRESSURE_PLATE = register(new BlockItem("light_weighted_pressure_plate", builder())); - public static final Item HEAVY_WEIGHTED_PRESSURE_PLATE = register(new BlockItem("heavy_weighted_pressure_plate", builder())); - public static final Item OAK_PRESSURE_PLATE = register(new BlockItem("oak_pressure_plate", builder())); - public static final Item SPRUCE_PRESSURE_PLATE = register(new BlockItem("spruce_pressure_plate", builder())); - public static final Item BIRCH_PRESSURE_PLATE = register(new BlockItem("birch_pressure_plate", builder())); - public static final Item JUNGLE_PRESSURE_PLATE = register(new BlockItem("jungle_pressure_plate", builder())); - public static final Item ACACIA_PRESSURE_PLATE = register(new BlockItem("acacia_pressure_plate", builder())); - public static final Item CHERRY_PRESSURE_PLATE = register(new BlockItem("cherry_pressure_plate", builder())); - public static final Item DARK_OAK_PRESSURE_PLATE = register(new BlockItem("dark_oak_pressure_plate", builder())); - public static final Item MANGROVE_PRESSURE_PLATE = register(new BlockItem("mangrove_pressure_plate", builder())); - public static final Item BAMBOO_PRESSURE_PLATE = register(new BlockItem("bamboo_pressure_plate", builder())); - public static final Item CRIMSON_PRESSURE_PLATE = register(new BlockItem("crimson_pressure_plate", builder())); - public static final Item WARPED_PRESSURE_PLATE = register(new BlockItem("warped_pressure_plate", builder())); - public static final Item IRON_DOOR = register(new BlockItem("iron_door", builder())); - public static final Item OAK_DOOR = register(new BlockItem("oak_door", builder())); - public static final Item SPRUCE_DOOR = register(new BlockItem("spruce_door", builder())); - public static final Item BIRCH_DOOR = register(new BlockItem("birch_door", builder())); - public static final Item JUNGLE_DOOR = register(new BlockItem("jungle_door", builder())); - public static final Item ACACIA_DOOR = register(new BlockItem("acacia_door", builder())); - public static final Item CHERRY_DOOR = register(new BlockItem("cherry_door", builder())); - public static final Item DARK_OAK_DOOR = register(new BlockItem("dark_oak_door", builder())); - public static final Item MANGROVE_DOOR = register(new BlockItem("mangrove_door", builder())); - 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())); - public static final Item BIRCH_TRAPDOOR = register(new BlockItem("birch_trapdoor", builder())); - public static final Item JUNGLE_TRAPDOOR = register(new BlockItem("jungle_trapdoor", builder())); - public static final Item ACACIA_TRAPDOOR = register(new BlockItem("acacia_trapdoor", builder())); - public static final Item CHERRY_TRAPDOOR = register(new BlockItem("cherry_trapdoor", builder())); - public static final Item DARK_OAK_TRAPDOOR = register(new BlockItem("dark_oak_trapdoor", builder())); - public static final Item MANGROVE_TRAPDOOR = register(new BlockItem("mangrove_trapdoor", builder())); - 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())); - public static final Item JUNGLE_FENCE_GATE = register(new BlockItem("jungle_fence_gate", builder())); - public static final Item ACACIA_FENCE_GATE = register(new BlockItem("acacia_fence_gate", builder())); - public static final Item CHERRY_FENCE_GATE = register(new BlockItem("cherry_fence_gate", builder())); - public static final Item DARK_OAK_FENCE_GATE = register(new BlockItem("dark_oak_fence_gate", builder())); - public static final Item MANGROVE_FENCE_GATE = register(new BlockItem("mangrove_fence_gate", builder())); - public static final Item BAMBOO_FENCE_GATE = register(new BlockItem("bamboo_fence_gate", builder())); - public static final Item CRIMSON_FENCE_GATE = register(new BlockItem("crimson_fence_gate", builder())); - public static final Item WARPED_FENCE_GATE = register(new BlockItem("warped_fence_gate", builder())); - public static final Item POWERED_RAIL = register(new BlockItem("powered_rail", builder())); - public static final Item DETECTOR_RAIL = register(new BlockItem("detector_rail", builder())); - public static final Item RAIL = register(new BlockItem("rail", builder())); - public static final Item ACTIVATOR_RAIL = register(new BlockItem("activator_rail", builder())); + public static final Item STONE = register(new BlockItem(builder(), Blocks.STONE)); + public static final Item GRANITE = register(new BlockItem(builder(), Blocks.GRANITE)); + public static final Item POLISHED_GRANITE = register(new BlockItem(builder(), Blocks.POLISHED_GRANITE)); + public static final Item DIORITE = register(new BlockItem(builder(), Blocks.DIORITE)); + public static final Item POLISHED_DIORITE = register(new BlockItem(builder(), Blocks.POLISHED_DIORITE)); + public static final Item ANDESITE = register(new BlockItem(builder(), Blocks.ANDESITE)); + public static final Item POLISHED_ANDESITE = register(new BlockItem(builder(), Blocks.POLISHED_ANDESITE)); + public static final Item DEEPSLATE = register(new BlockItem(builder(), Blocks.DEEPSLATE)); + public static final Item COBBLED_DEEPSLATE = register(new BlockItem(builder(), Blocks.COBBLED_DEEPSLATE)); + public static final Item POLISHED_DEEPSLATE = register(new BlockItem(builder(), Blocks.POLISHED_DEEPSLATE)); + public static final Item CALCITE = register(new BlockItem(builder(), Blocks.CALCITE)); + public static final Item TUFF = register(new BlockItem(builder(), Blocks.TUFF)); + public static final Item TUFF_SLAB = register(new BlockItem(builder(), Blocks.TUFF_SLAB)); + public static final Item TUFF_STAIRS = register(new BlockItem(builder(), Blocks.TUFF_STAIRS)); + public static final Item TUFF_WALL = register(new BlockItem(builder(), Blocks.TUFF_WALL)); + public static final Item CHISELED_TUFF = register(new BlockItem(builder(), Blocks.CHISELED_TUFF)); + public static final Item POLISHED_TUFF = register(new BlockItem(builder(), Blocks.POLISHED_TUFF)); + public static final Item POLISHED_TUFF_SLAB = register(new BlockItem(builder(), Blocks.POLISHED_TUFF_SLAB)); + public static final Item POLISHED_TUFF_STAIRS = register(new BlockItem(builder(), Blocks.POLISHED_TUFF_STAIRS)); + public static final Item POLISHED_TUFF_WALL = register(new BlockItem(builder(), Blocks.POLISHED_TUFF_WALL)); + public static final Item TUFF_BRICKS = register(new BlockItem(builder(), Blocks.TUFF_BRICKS)); + public static final Item TUFF_BRICK_SLAB = register(new BlockItem(builder(), Blocks.TUFF_BRICK_SLAB)); + public static final Item TUFF_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.TUFF_BRICK_STAIRS)); + public static final Item TUFF_BRICK_WALL = register(new BlockItem(builder(), Blocks.TUFF_BRICK_WALL)); + public static final Item CHISELED_TUFF_BRICKS = register(new BlockItem(builder(), Blocks.CHISELED_TUFF_BRICKS)); + public static final Item DRIPSTONE_BLOCK = register(new BlockItem(builder(), Blocks.DRIPSTONE_BLOCK)); + public static final Item GRASS_BLOCK = register(new BlockItem(builder(), Blocks.GRASS_BLOCK)); + public static final Item DIRT = register(new BlockItem(builder(), Blocks.DIRT)); + public static final Item COARSE_DIRT = register(new BlockItem(builder(), Blocks.COARSE_DIRT)); + public static final Item PODZOL = register(new BlockItem(builder(), Blocks.PODZOL)); + public static final Item ROOTED_DIRT = register(new BlockItem(builder(), Blocks.ROOTED_DIRT)); + public static final Item MUD = register(new BlockItem(builder(), Blocks.MUD)); + public static final Item CRIMSON_NYLIUM = register(new BlockItem(builder(), Blocks.CRIMSON_NYLIUM)); + public static final Item WARPED_NYLIUM = register(new BlockItem(builder(), Blocks.WARPED_NYLIUM)); + public static final Item COBBLESTONE = register(new BlockItem(builder(), Blocks.COBBLESTONE)); + public static final Item OAK_PLANKS = register(new BlockItem(builder(), Blocks.OAK_PLANKS)); + public static final Item SPRUCE_PLANKS = register(new BlockItem(builder(), Blocks.SPRUCE_PLANKS)); + public static final Item BIRCH_PLANKS = register(new BlockItem(builder(), Blocks.BIRCH_PLANKS)); + public static final Item JUNGLE_PLANKS = register(new BlockItem(builder(), Blocks.JUNGLE_PLANKS)); + public static final Item ACACIA_PLANKS = register(new BlockItem(builder(), Blocks.ACACIA_PLANKS)); + public static final Item CHERRY_PLANKS = register(new BlockItem(builder(), Blocks.CHERRY_PLANKS)); + public static final Item DARK_OAK_PLANKS = register(new BlockItem(builder(), Blocks.DARK_OAK_PLANKS)); + public static final Item MANGROVE_PLANKS = register(new BlockItem(builder(), Blocks.MANGROVE_PLANKS)); + public static final Item BAMBOO_PLANKS = register(new BlockItem(builder(), Blocks.BAMBOO_PLANKS)); + public static final Item CRIMSON_PLANKS = register(new BlockItem(builder(), Blocks.CRIMSON_PLANKS)); + public static final Item WARPED_PLANKS = register(new BlockItem(builder(), Blocks.WARPED_PLANKS)); + public static final Item BAMBOO_MOSAIC = register(new BlockItem(builder(), Blocks.BAMBOO_MOSAIC)); + public static final Item OAK_SAPLING = register(new BlockItem(builder(), Blocks.OAK_SAPLING)); + public static final Item SPRUCE_SAPLING = register(new BlockItem(builder(), Blocks.SPRUCE_SAPLING)); + public static final Item BIRCH_SAPLING = register(new BlockItem(builder(), Blocks.BIRCH_SAPLING)); + public static final Item JUNGLE_SAPLING = register(new BlockItem(builder(), Blocks.JUNGLE_SAPLING)); + public static final Item ACACIA_SAPLING = register(new BlockItem(builder(), Blocks.ACACIA_SAPLING)); + public static final Item CHERRY_SAPLING = register(new BlockItem(builder(), Blocks.CHERRY_SAPLING)); + public static final Item DARK_OAK_SAPLING = register(new BlockItem(builder(), Blocks.DARK_OAK_SAPLING)); + public static final Item MANGROVE_PROPAGULE = register(new BlockItem(builder(), Blocks.MANGROVE_PROPAGULE)); + public static final Item BEDROCK = register(new BlockItem(builder(), Blocks.BEDROCK)); + public static final Item SAND = register(new BlockItem(builder(), Blocks.SAND)); + public static final Item SUSPICIOUS_SAND = register(new BlockItem(builder(), Blocks.SUSPICIOUS_SAND)); + public static final Item SUSPICIOUS_GRAVEL = register(new BlockItem(builder(), Blocks.SUSPICIOUS_GRAVEL)); + public static final Item RED_SAND = register(new BlockItem(builder(), Blocks.RED_SAND)); + public static final Item GRAVEL = register(new BlockItem(builder(), Blocks.GRAVEL)); + public static final Item COAL_ORE = register(new BlockItem(builder(), Blocks.COAL_ORE)); + public static final Item DEEPSLATE_COAL_ORE = register(new BlockItem(builder(), Blocks.DEEPSLATE_COAL_ORE)); + public static final Item IRON_ORE = register(new BlockItem(builder(), Blocks.IRON_ORE)); + public static final Item DEEPSLATE_IRON_ORE = register(new BlockItem(builder(), Blocks.DEEPSLATE_IRON_ORE)); + public static final Item COPPER_ORE = register(new BlockItem(builder(), Blocks.COPPER_ORE)); + public static final Item DEEPSLATE_COPPER_ORE = register(new BlockItem(builder(), Blocks.DEEPSLATE_COPPER_ORE)); + public static final Item GOLD_ORE = register(new BlockItem(builder(), Blocks.GOLD_ORE)); + public static final Item DEEPSLATE_GOLD_ORE = register(new BlockItem(builder(), Blocks.DEEPSLATE_GOLD_ORE)); + public static final Item REDSTONE_ORE = register(new BlockItem(builder(), Blocks.REDSTONE_ORE)); + public static final Item DEEPSLATE_REDSTONE_ORE = register(new BlockItem(builder(), Blocks.DEEPSLATE_REDSTONE_ORE)); + public static final Item EMERALD_ORE = register(new BlockItem(builder(), Blocks.EMERALD_ORE)); + public static final Item DEEPSLATE_EMERALD_ORE = register(new BlockItem(builder(), Blocks.DEEPSLATE_EMERALD_ORE)); + public static final Item LAPIS_ORE = register(new BlockItem(builder(), Blocks.LAPIS_ORE)); + public static final Item DEEPSLATE_LAPIS_ORE = register(new BlockItem(builder(), Blocks.DEEPSLATE_LAPIS_ORE)); + public static final Item DIAMOND_ORE = register(new BlockItem(builder(), Blocks.DIAMOND_ORE)); + public static final Item DEEPSLATE_DIAMOND_ORE = register(new BlockItem(builder(), Blocks.DEEPSLATE_DIAMOND_ORE)); + public static final Item NETHER_GOLD_ORE = register(new BlockItem(builder(), Blocks.NETHER_GOLD_ORE)); + public static final Item NETHER_QUARTZ_ORE = register(new BlockItem(builder(), Blocks.NETHER_QUARTZ_ORE)); + public static final Item ANCIENT_DEBRIS = register(new BlockItem(builder(), Blocks.ANCIENT_DEBRIS)); + public static final Item COAL_BLOCK = register(new BlockItem(builder(), Blocks.COAL_BLOCK)); + public static final Item RAW_IRON_BLOCK = register(new BlockItem(builder(), Blocks.RAW_IRON_BLOCK)); + public static final Item RAW_COPPER_BLOCK = register(new BlockItem(builder(), Blocks.RAW_COPPER_BLOCK)); + public static final Item RAW_GOLD_BLOCK = register(new BlockItem(builder(), Blocks.RAW_GOLD_BLOCK)); + public static final Item HEAVY_CORE = register(new BlockItem(builder(), Blocks.HEAVY_CORE)); + public static final Item AMETHYST_BLOCK = register(new BlockItem(builder(), Blocks.AMETHYST_BLOCK)); + public static final Item BUDDING_AMETHYST = register(new BlockItem(builder(), Blocks.BUDDING_AMETHYST)); + public static final Item IRON_BLOCK = register(new BlockItem(builder(), Blocks.IRON_BLOCK)); + public static final Item COPPER_BLOCK = register(new BlockItem(builder(), Blocks.COPPER_BLOCK)); + public static final Item GOLD_BLOCK = register(new BlockItem(builder(), Blocks.GOLD_BLOCK)); + public static final Item DIAMOND_BLOCK = register(new BlockItem(builder(), Blocks.DIAMOND_BLOCK)); + public static final Item NETHERITE_BLOCK = register(new BlockItem(builder(), Blocks.NETHERITE_BLOCK)); + public static final Item EXPOSED_COPPER = register(new BlockItem(builder(), Blocks.EXPOSED_COPPER)); + public static final Item WEATHERED_COPPER = register(new BlockItem(builder(), Blocks.WEATHERED_COPPER)); + public static final Item OXIDIZED_COPPER = register(new BlockItem(builder(), Blocks.OXIDIZED_COPPER)); + public static final Item CHISELED_COPPER = register(new BlockItem(builder(), Blocks.CHISELED_COPPER)); + public static final Item EXPOSED_CHISELED_COPPER = register(new BlockItem(builder(), Blocks.EXPOSED_CHISELED_COPPER)); + public static final Item WEATHERED_CHISELED_COPPER = register(new BlockItem(builder(), Blocks.WEATHERED_CHISELED_COPPER)); + public static final Item OXIDIZED_CHISELED_COPPER = register(new BlockItem(builder(), Blocks.OXIDIZED_CHISELED_COPPER)); + public static final Item CUT_COPPER = register(new BlockItem(builder(), Blocks.CUT_COPPER)); + public static final Item EXPOSED_CUT_COPPER = register(new BlockItem(builder(), Blocks.EXPOSED_CUT_COPPER)); + public static final Item WEATHERED_CUT_COPPER = register(new BlockItem(builder(), Blocks.WEATHERED_CUT_COPPER)); + public static final Item OXIDIZED_CUT_COPPER = register(new BlockItem(builder(), Blocks.OXIDIZED_CUT_COPPER)); + public static final Item CUT_COPPER_STAIRS = register(new BlockItem(builder(), Blocks.CUT_COPPER_STAIRS)); + public static final Item EXPOSED_CUT_COPPER_STAIRS = register(new BlockItem(builder(), Blocks.EXPOSED_CUT_COPPER_STAIRS)); + public static final Item WEATHERED_CUT_COPPER_STAIRS = register(new BlockItem(builder(), Blocks.WEATHERED_CUT_COPPER_STAIRS)); + public static final Item OXIDIZED_CUT_COPPER_STAIRS = register(new BlockItem(builder(), Blocks.OXIDIZED_CUT_COPPER_STAIRS)); + public static final Item CUT_COPPER_SLAB = register(new BlockItem(builder(), Blocks.CUT_COPPER_SLAB)); + public static final Item EXPOSED_CUT_COPPER_SLAB = register(new BlockItem(builder(), Blocks.EXPOSED_CUT_COPPER_SLAB)); + public static final Item WEATHERED_CUT_COPPER_SLAB = register(new BlockItem(builder(), Blocks.WEATHERED_CUT_COPPER_SLAB)); + public static final Item OXIDIZED_CUT_COPPER_SLAB = register(new BlockItem(builder(), Blocks.OXIDIZED_CUT_COPPER_SLAB)); + public static final Item WAXED_COPPER_BLOCK = register(new BlockItem(builder(), Blocks.WAXED_COPPER_BLOCK)); + public static final Item WAXED_EXPOSED_COPPER = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_COPPER)); + public static final Item WAXED_WEATHERED_COPPER = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_COPPER)); + public static final Item WAXED_OXIDIZED_COPPER = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_COPPER)); + public static final Item WAXED_CHISELED_COPPER = register(new BlockItem(builder(), Blocks.WAXED_CHISELED_COPPER)); + public static final Item WAXED_EXPOSED_CHISELED_COPPER = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_CHISELED_COPPER)); + public static final Item WAXED_WEATHERED_CHISELED_COPPER = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_CHISELED_COPPER)); + public static final Item WAXED_OXIDIZED_CHISELED_COPPER = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_CHISELED_COPPER)); + public static final Item WAXED_CUT_COPPER = register(new BlockItem(builder(), Blocks.WAXED_CUT_COPPER)); + public static final Item WAXED_EXPOSED_CUT_COPPER = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_CUT_COPPER)); + public static final Item WAXED_WEATHERED_CUT_COPPER = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_CUT_COPPER)); + public static final Item WAXED_OXIDIZED_CUT_COPPER = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_CUT_COPPER)); + public static final Item WAXED_CUT_COPPER_STAIRS = register(new BlockItem(builder(), Blocks.WAXED_CUT_COPPER_STAIRS)); + public static final Item WAXED_EXPOSED_CUT_COPPER_STAIRS = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_CUT_COPPER_STAIRS)); + public static final Item WAXED_WEATHERED_CUT_COPPER_STAIRS = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_CUT_COPPER_STAIRS)); + public static final Item WAXED_OXIDIZED_CUT_COPPER_STAIRS = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_CUT_COPPER_STAIRS)); + public static final Item WAXED_CUT_COPPER_SLAB = register(new BlockItem(builder(), Blocks.WAXED_CUT_COPPER_SLAB)); + public static final Item WAXED_EXPOSED_CUT_COPPER_SLAB = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_CUT_COPPER_SLAB)); + public static final Item WAXED_WEATHERED_CUT_COPPER_SLAB = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_CUT_COPPER_SLAB)); + public static final Item WAXED_OXIDIZED_CUT_COPPER_SLAB = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_CUT_COPPER_SLAB)); + public static final Item OAK_LOG = register(new BlockItem(builder(), Blocks.OAK_LOG)); + public static final Item SPRUCE_LOG = register(new BlockItem(builder(), Blocks.SPRUCE_LOG)); + public static final Item BIRCH_LOG = register(new BlockItem(builder(), Blocks.BIRCH_LOG)); + public static final Item JUNGLE_LOG = register(new BlockItem(builder(), Blocks.JUNGLE_LOG)); + public static final Item ACACIA_LOG = register(new BlockItem(builder(), Blocks.ACACIA_LOG)); + public static final Item CHERRY_LOG = register(new BlockItem(builder(), Blocks.CHERRY_LOG)); + public static final Item DARK_OAK_LOG = register(new BlockItem(builder(), Blocks.DARK_OAK_LOG)); + public static final Item MANGROVE_LOG = register(new BlockItem(builder(), Blocks.MANGROVE_LOG)); + public static final Item MANGROVE_ROOTS = register(new BlockItem(builder(), Blocks.MANGROVE_ROOTS)); + public static final Item MUDDY_MANGROVE_ROOTS = register(new BlockItem(builder(), Blocks.MUDDY_MANGROVE_ROOTS)); + public static final Item CRIMSON_STEM = register(new BlockItem(builder(), Blocks.CRIMSON_STEM)); + public static final Item WARPED_STEM = register(new BlockItem(builder(), Blocks.WARPED_STEM)); + public static final Item BAMBOO_BLOCK = register(new BlockItem(builder(), Blocks.BAMBOO_BLOCK)); + public static final Item STRIPPED_OAK_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_OAK_LOG)); + public static final Item STRIPPED_SPRUCE_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_SPRUCE_LOG)); + public static final Item STRIPPED_BIRCH_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_BIRCH_LOG)); + public static final Item STRIPPED_JUNGLE_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_JUNGLE_LOG)); + public static final Item STRIPPED_ACACIA_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_ACACIA_LOG)); + public static final Item STRIPPED_CHERRY_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_CHERRY_LOG)); + public static final Item STRIPPED_DARK_OAK_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_DARK_OAK_LOG)); + public static final Item STRIPPED_MANGROVE_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_MANGROVE_LOG)); + public static final Item STRIPPED_CRIMSON_STEM = register(new BlockItem(builder(), Blocks.STRIPPED_CRIMSON_STEM)); + public static final Item STRIPPED_WARPED_STEM = register(new BlockItem(builder(), Blocks.STRIPPED_WARPED_STEM)); + public static final Item STRIPPED_OAK_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_OAK_WOOD)); + public static final Item STRIPPED_SPRUCE_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_SPRUCE_WOOD)); + public static final Item STRIPPED_BIRCH_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_BIRCH_WOOD)); + public static final Item STRIPPED_JUNGLE_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_JUNGLE_WOOD)); + public static final Item STRIPPED_ACACIA_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_ACACIA_WOOD)); + public static final Item STRIPPED_CHERRY_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_CHERRY_WOOD)); + public static final Item STRIPPED_DARK_OAK_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_DARK_OAK_WOOD)); + public static final Item STRIPPED_MANGROVE_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_MANGROVE_WOOD)); + public static final Item STRIPPED_CRIMSON_HYPHAE = register(new BlockItem(builder(), Blocks.STRIPPED_CRIMSON_HYPHAE)); + public static final Item STRIPPED_WARPED_HYPHAE = register(new BlockItem(builder(), Blocks.STRIPPED_WARPED_HYPHAE)); + public static final Item STRIPPED_BAMBOO_BLOCK = register(new BlockItem(builder(), Blocks.STRIPPED_BAMBOO_BLOCK)); + public static final Item OAK_WOOD = register(new BlockItem(builder(), Blocks.OAK_WOOD)); + public static final Item SPRUCE_WOOD = register(new BlockItem(builder(), Blocks.SPRUCE_WOOD)); + public static final Item BIRCH_WOOD = register(new BlockItem(builder(), Blocks.BIRCH_WOOD)); + public static final Item JUNGLE_WOOD = register(new BlockItem(builder(), Blocks.JUNGLE_WOOD)); + public static final Item ACACIA_WOOD = register(new BlockItem(builder(), Blocks.ACACIA_WOOD)); + public static final Item CHERRY_WOOD = register(new BlockItem(builder(), Blocks.CHERRY_WOOD)); + public static final Item DARK_OAK_WOOD = register(new BlockItem(builder(), Blocks.DARK_OAK_WOOD)); + public static final Item MANGROVE_WOOD = register(new BlockItem(builder(), Blocks.MANGROVE_WOOD)); + public static final Item CRIMSON_HYPHAE = register(new BlockItem(builder(), Blocks.CRIMSON_HYPHAE)); + public static final Item WARPED_HYPHAE = register(new BlockItem(builder(), Blocks.WARPED_HYPHAE)); + public static final Item OAK_LEAVES = register(new BlockItem(builder(), Blocks.OAK_LEAVES)); + public static final Item SPRUCE_LEAVES = register(new BlockItem(builder(), Blocks.SPRUCE_LEAVES)); + public static final Item BIRCH_LEAVES = register(new BlockItem(builder(), Blocks.BIRCH_LEAVES)); + public static final Item JUNGLE_LEAVES = register(new BlockItem(builder(), Blocks.JUNGLE_LEAVES)); + public static final Item ACACIA_LEAVES = register(new BlockItem(builder(), Blocks.ACACIA_LEAVES)); + public static final Item CHERRY_LEAVES = register(new BlockItem(builder(), Blocks.CHERRY_LEAVES)); + public static final Item DARK_OAK_LEAVES = register(new BlockItem(builder(), Blocks.DARK_OAK_LEAVES)); + public static final Item MANGROVE_LEAVES = register(new BlockItem(builder(), Blocks.MANGROVE_LEAVES)); + public static final Item AZALEA_LEAVES = register(new BlockItem(builder(), Blocks.AZALEA_LEAVES)); + public static final Item FLOWERING_AZALEA_LEAVES = register(new BlockItem(builder(), Blocks.FLOWERING_AZALEA_LEAVES)); + public static final Item SPONGE = register(new BlockItem(builder(), Blocks.SPONGE)); + public static final Item WET_SPONGE = register(new BlockItem(builder(), Blocks.WET_SPONGE)); + public static final Item GLASS = register(new BlockItem(builder(), Blocks.GLASS)); + public static final Item TINTED_GLASS = register(new BlockItem(builder(), Blocks.TINTED_GLASS)); + public static final Item LAPIS_BLOCK = register(new BlockItem(builder(), Blocks.LAPIS_BLOCK)); + public static final Item SANDSTONE = register(new BlockItem(builder(), Blocks.SANDSTONE)); + public static final Item CHISELED_SANDSTONE = register(new BlockItem(builder(), Blocks.CHISELED_SANDSTONE)); + public static final Item CUT_SANDSTONE = register(new BlockItem(builder(), Blocks.CUT_SANDSTONE)); + public static final Item COBWEB = register(new BlockItem(builder(), Blocks.COBWEB)); + public static final Item SHORT_GRASS = register(new BlockItem(builder(), Blocks.SHORT_GRASS)); + public static final Item FERN = register(new BlockItem(builder(), Blocks.FERN)); + public static final Item AZALEA = register(new BlockItem(builder(), Blocks.AZALEA)); + public static final Item FLOWERING_AZALEA = register(new BlockItem(builder(), Blocks.FLOWERING_AZALEA)); + public static final Item DEAD_BUSH = register(new BlockItem(builder(), Blocks.DEAD_BUSH)); + public static final Item SEAGRASS = register(new BlockItem(builder(), Blocks.SEAGRASS)); + public static final Item SEA_PICKLE = register(new BlockItem(builder(), Blocks.SEA_PICKLE)); + public static final Item WHITE_WOOL = register(new BlockItem(builder(), Blocks.WHITE_WOOL)); + public static final Item ORANGE_WOOL = register(new BlockItem(builder(), Blocks.ORANGE_WOOL)); + public static final Item MAGENTA_WOOL = register(new BlockItem(builder(), Blocks.MAGENTA_WOOL)); + public static final Item LIGHT_BLUE_WOOL = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_WOOL)); + public static final Item YELLOW_WOOL = register(new BlockItem(builder(), Blocks.YELLOW_WOOL)); + public static final Item LIME_WOOL = register(new BlockItem(builder(), Blocks.LIME_WOOL)); + public static final Item PINK_WOOL = register(new BlockItem(builder(), Blocks.PINK_WOOL)); + public static final Item GRAY_WOOL = register(new BlockItem(builder(), Blocks.GRAY_WOOL)); + public static final Item LIGHT_GRAY_WOOL = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_WOOL)); + public static final Item CYAN_WOOL = register(new BlockItem(builder(), Blocks.CYAN_WOOL)); + public static final Item PURPLE_WOOL = register(new BlockItem(builder(), Blocks.PURPLE_WOOL)); + public static final Item BLUE_WOOL = register(new BlockItem(builder(), Blocks.BLUE_WOOL)); + public static final Item BROWN_WOOL = register(new BlockItem(builder(), Blocks.BROWN_WOOL)); + public static final Item GREEN_WOOL = register(new BlockItem(builder(), Blocks.GREEN_WOOL)); + public static final Item RED_WOOL = register(new BlockItem(builder(), Blocks.RED_WOOL)); + public static final Item BLACK_WOOL = register(new BlockItem(builder(), Blocks.BLACK_WOOL)); + public static final Item DANDELION = register(new BlockItem(builder(), Blocks.DANDELION)); + public static final Item POPPY = register(new BlockItem(builder(), Blocks.POPPY)); + public static final Item BLUE_ORCHID = register(new BlockItem(builder(), Blocks.BLUE_ORCHID)); + public static final Item ALLIUM = register(new BlockItem(builder(), Blocks.ALLIUM)); + public static final Item AZURE_BLUET = register(new BlockItem(builder(), Blocks.AZURE_BLUET)); + public static final Item RED_TULIP = register(new BlockItem(builder(), Blocks.RED_TULIP)); + public static final Item ORANGE_TULIP = register(new BlockItem(builder(), Blocks.ORANGE_TULIP)); + public static final Item WHITE_TULIP = register(new BlockItem(builder(), Blocks.WHITE_TULIP)); + public static final Item PINK_TULIP = register(new BlockItem(builder(), Blocks.PINK_TULIP)); + public static final Item OXEYE_DAISY = register(new BlockItem(builder(), Blocks.OXEYE_DAISY)); + public static final Item CORNFLOWER = register(new BlockItem(builder(), Blocks.CORNFLOWER)); + public static final Item LILY_OF_THE_VALLEY = register(new BlockItem(builder(), Blocks.LILY_OF_THE_VALLEY)); + public static final Item WITHER_ROSE = register(new BlockItem(builder(), Blocks.WITHER_ROSE)); + public static final Item TORCHFLOWER = register(new BlockItem(builder(), Blocks.TORCHFLOWER)); + public static final Item PITCHER_PLANT = register(new BlockItem(builder(), Blocks.PITCHER_PLANT)); + public static final Item SPORE_BLOSSOM = register(new BlockItem(builder(), Blocks.SPORE_BLOSSOM)); + public static final Item BROWN_MUSHROOM = register(new BlockItem(builder(), Blocks.BROWN_MUSHROOM)); + public static final Item RED_MUSHROOM = register(new BlockItem(builder(), Blocks.RED_MUSHROOM)); + public static final Item CRIMSON_FUNGUS = register(new BlockItem(builder(), Blocks.CRIMSON_FUNGUS)); + public static final Item WARPED_FUNGUS = register(new BlockItem(builder(), Blocks.WARPED_FUNGUS)); + public static final Item CRIMSON_ROOTS = register(new BlockItem(builder(), Blocks.CRIMSON_ROOTS)); + public static final Item WARPED_ROOTS = register(new BlockItem(builder(), Blocks.WARPED_ROOTS)); + public static final Item NETHER_SPROUTS = register(new BlockItem(builder(), Blocks.NETHER_SPROUTS)); + public static final Item WEEPING_VINES = register(new BlockItem(builder(), Blocks.WEEPING_VINES)); + public static final Item TWISTING_VINES = register(new BlockItem(builder(), Blocks.TWISTING_VINES)); + public static final Item SUGAR_CANE = register(new BlockItem(builder(), Blocks.SUGAR_CANE)); + public static final Item KELP = register(new BlockItem(builder(), Blocks.KELP)); + public static final Item MOSS_CARPET = register(new BlockItem(builder(), Blocks.MOSS_CARPET)); + public static final Item PINK_PETALS = register(new BlockItem(builder(), Blocks.PINK_PETALS)); + public static final Item MOSS_BLOCK = register(new BlockItem(builder(), Blocks.MOSS_BLOCK)); + public static final Item HANGING_ROOTS = register(new BlockItem(builder(), Blocks.HANGING_ROOTS)); + public static final Item BIG_DRIPLEAF = register(new BlockItem(builder(), Blocks.BIG_DRIPLEAF, Blocks.BIG_DRIPLEAF_STEM)); + public static final Item SMALL_DRIPLEAF = register(new BlockItem(builder(), Blocks.SMALL_DRIPLEAF)); + public static final Item BAMBOO = register(new BlockItem(builder(), Blocks.BAMBOO)); + public static final Item OAK_SLAB = register(new BlockItem(builder(), Blocks.OAK_SLAB)); + public static final Item SPRUCE_SLAB = register(new BlockItem(builder(), Blocks.SPRUCE_SLAB)); + public static final Item BIRCH_SLAB = register(new BlockItem(builder(), Blocks.BIRCH_SLAB)); + public static final Item JUNGLE_SLAB = register(new BlockItem(builder(), Blocks.JUNGLE_SLAB)); + public static final Item ACACIA_SLAB = register(new BlockItem(builder(), Blocks.ACACIA_SLAB)); + public static final Item CHERRY_SLAB = register(new BlockItem(builder(), Blocks.CHERRY_SLAB)); + public static final Item DARK_OAK_SLAB = register(new BlockItem(builder(), Blocks.DARK_OAK_SLAB)); + public static final Item MANGROVE_SLAB = register(new BlockItem(builder(), Blocks.MANGROVE_SLAB)); + public static final Item BAMBOO_SLAB = register(new BlockItem(builder(), Blocks.BAMBOO_SLAB)); + public static final Item BAMBOO_MOSAIC_SLAB = register(new BlockItem(builder(), Blocks.BAMBOO_MOSAIC_SLAB)); + public static final Item CRIMSON_SLAB = register(new BlockItem(builder(), Blocks.CRIMSON_SLAB)); + public static final Item WARPED_SLAB = register(new BlockItem(builder(), Blocks.WARPED_SLAB)); + public static final Item STONE_SLAB = register(new BlockItem(builder(), Blocks.STONE_SLAB)); + public static final Item SMOOTH_STONE_SLAB = register(new BlockItem(builder(), Blocks.SMOOTH_STONE_SLAB)); + public static final Item SANDSTONE_SLAB = register(new BlockItem(builder(), Blocks.SANDSTONE_SLAB)); + public static final Item CUT_SANDSTONE_SLAB = register(new BlockItem(builder(), Blocks.CUT_SANDSTONE_SLAB)); + public static final Item PETRIFIED_OAK_SLAB = register(new BlockItem(builder(), Blocks.PETRIFIED_OAK_SLAB)); + public static final Item COBBLESTONE_SLAB = register(new BlockItem(builder(), Blocks.COBBLESTONE_SLAB)); + public static final Item BRICK_SLAB = register(new BlockItem(builder(), Blocks.BRICK_SLAB)); + public static final Item STONE_BRICK_SLAB = register(new BlockItem(builder(), Blocks.STONE_BRICK_SLAB)); + public static final Item MUD_BRICK_SLAB = register(new BlockItem(builder(), Blocks.MUD_BRICK_SLAB)); + public static final Item NETHER_BRICK_SLAB = register(new BlockItem(builder(), Blocks.NETHER_BRICK_SLAB)); + public static final Item QUARTZ_SLAB = register(new BlockItem(builder(), Blocks.QUARTZ_SLAB)); + public static final Item RED_SANDSTONE_SLAB = register(new BlockItem(builder(), Blocks.RED_SANDSTONE_SLAB)); + public static final Item CUT_RED_SANDSTONE_SLAB = register(new BlockItem(builder(), Blocks.CUT_RED_SANDSTONE_SLAB)); + public static final Item PURPUR_SLAB = register(new BlockItem(builder(), Blocks.PURPUR_SLAB)); + public static final Item PRISMARINE_SLAB = register(new BlockItem(builder(), Blocks.PRISMARINE_SLAB)); + public static final Item PRISMARINE_BRICK_SLAB = register(new BlockItem(builder(), Blocks.PRISMARINE_BRICK_SLAB)); + public static final Item DARK_PRISMARINE_SLAB = register(new BlockItem(builder(), Blocks.DARK_PRISMARINE_SLAB)); + public static final Item SMOOTH_QUARTZ = register(new BlockItem(builder(), Blocks.SMOOTH_QUARTZ)); + public static final Item SMOOTH_RED_SANDSTONE = register(new BlockItem(builder(), Blocks.SMOOTH_RED_SANDSTONE)); + public static final Item SMOOTH_SANDSTONE = register(new BlockItem(builder(), Blocks.SMOOTH_SANDSTONE)); + public static final Item SMOOTH_STONE = register(new BlockItem(builder(), Blocks.SMOOTH_STONE)); + public static final Item BRICKS = register(new BlockItem(builder(), Blocks.BRICKS)); + public static final Item BOOKSHELF = register(new BlockItem(builder(), Blocks.BOOKSHELF)); + public static final Item CHISELED_BOOKSHELF = register(new BlockItem(builder(), Blocks.CHISELED_BOOKSHELF)); + public static final Item DECORATED_POT = register(new DecoratedPotItem(builder(), Blocks.DECORATED_POT)); + public static final Item MOSSY_COBBLESTONE = register(new BlockItem(builder(), Blocks.MOSSY_COBBLESTONE)); + public static final Item OBSIDIAN = register(new BlockItem(builder(), Blocks.OBSIDIAN)); + public static final Item TORCH = register(new BlockItem(builder(), Blocks.TORCH, Blocks.WALL_TORCH)); + public static final Item END_ROD = register(new BlockItem(builder(), Blocks.END_ROD)); + public static final Item CHORUS_PLANT = register(new BlockItem(builder(), Blocks.CHORUS_PLANT)); + public static final Item CHORUS_FLOWER = register(new BlockItem(builder(), Blocks.CHORUS_FLOWER)); + public static final Item PURPUR_BLOCK = register(new BlockItem(builder(), Blocks.PURPUR_BLOCK)); + public static final Item PURPUR_PILLAR = register(new BlockItem(builder(), Blocks.PURPUR_PILLAR)); + public static final Item PURPUR_STAIRS = register(new BlockItem(builder(), Blocks.PURPUR_STAIRS)); + public static final Item SPAWNER = register(new BlockItem(builder(), Blocks.SPAWNER)); + public static final Item CHEST = register(new BlockItem(builder(), Blocks.CHEST)); + public static final Item CRAFTING_TABLE = register(new BlockItem(builder(), Blocks.CRAFTING_TABLE)); + public static final Item FARMLAND = register(new BlockItem(builder(), Blocks.FARMLAND)); + public static final Item FURNACE = register(new BlockItem(builder(), Blocks.FURNACE)); + public static final Item LADDER = register(new BlockItem(builder(), Blocks.LADDER)); + public static final Item COBBLESTONE_STAIRS = register(new BlockItem(builder(), Blocks.COBBLESTONE_STAIRS)); + public static final Item SNOW = register(new BlockItem(builder(), Blocks.SNOW)); + public static final Item ICE = register(new BlockItem(builder(), Blocks.ICE)); + public static final Item SNOW_BLOCK = register(new BlockItem(builder(), Blocks.SNOW_BLOCK)); + public static final Item CACTUS = register(new BlockItem(builder(), Blocks.CACTUS)); + public static final Item CLAY = register(new BlockItem(builder(), Blocks.CLAY)); + public static final Item JUKEBOX = register(new BlockItem(builder(), Blocks.JUKEBOX)); + public static final Item OAK_FENCE = register(new BlockItem(builder(), Blocks.OAK_FENCE)); + public static final Item SPRUCE_FENCE = register(new BlockItem(builder(), Blocks.SPRUCE_FENCE)); + public static final Item BIRCH_FENCE = register(new BlockItem(builder(), Blocks.BIRCH_FENCE)); + public static final Item JUNGLE_FENCE = register(new BlockItem(builder(), Blocks.JUNGLE_FENCE)); + public static final Item ACACIA_FENCE = register(new BlockItem(builder(), Blocks.ACACIA_FENCE)); + public static final Item CHERRY_FENCE = register(new BlockItem(builder(), Blocks.CHERRY_FENCE)); + public static final Item DARK_OAK_FENCE = register(new BlockItem(builder(), Blocks.DARK_OAK_FENCE)); + public static final Item MANGROVE_FENCE = register(new BlockItem(builder(), Blocks.MANGROVE_FENCE)); + public static final Item BAMBOO_FENCE = register(new BlockItem(builder(), Blocks.BAMBOO_FENCE)); + public static final Item CRIMSON_FENCE = register(new BlockItem(builder(), Blocks.CRIMSON_FENCE)); + public static final Item WARPED_FENCE = register(new BlockItem(builder(), Blocks.WARPED_FENCE)); + public static final Item PUMPKIN = register(new BlockItem(builder(), Blocks.PUMPKIN)); + public static final Item CARVED_PUMPKIN = register(new BlockItem(builder(), Blocks.CARVED_PUMPKIN)); + public static final Item JACK_O_LANTERN = register(new BlockItem(builder(), Blocks.JACK_O_LANTERN)); + public static final Item NETHERRACK = register(new BlockItem(builder(), Blocks.NETHERRACK)); + public static final Item SOUL_SAND = register(new BlockItem(builder(), Blocks.SOUL_SAND)); + public static final Item SOUL_SOIL = register(new BlockItem(builder(), Blocks.SOUL_SOIL)); + public static final Item BASALT = register(new BlockItem(builder(), Blocks.BASALT)); + public static final Item POLISHED_BASALT = register(new BlockItem(builder(), Blocks.POLISHED_BASALT)); + public static final Item SMOOTH_BASALT = register(new BlockItem(builder(), Blocks.SMOOTH_BASALT)); + public static final Item SOUL_TORCH = register(new BlockItem(builder(), Blocks.SOUL_TORCH, Blocks.SOUL_WALL_TORCH)); + public static final Item GLOWSTONE = register(new BlockItem(builder(), Blocks.GLOWSTONE)); + public static final Item INFESTED_STONE = register(new BlockItem(builder(), Blocks.INFESTED_STONE)); + public static final Item INFESTED_COBBLESTONE = register(new BlockItem(builder(), Blocks.INFESTED_COBBLESTONE)); + public static final Item INFESTED_STONE_BRICKS = register(new BlockItem(builder(), Blocks.INFESTED_STONE_BRICKS)); + public static final Item INFESTED_MOSSY_STONE_BRICKS = register(new BlockItem(builder(), Blocks.INFESTED_MOSSY_STONE_BRICKS)); + public static final Item INFESTED_CRACKED_STONE_BRICKS = register(new BlockItem(builder(), Blocks.INFESTED_CRACKED_STONE_BRICKS)); + public static final Item INFESTED_CHISELED_STONE_BRICKS = register(new BlockItem(builder(), Blocks.INFESTED_CHISELED_STONE_BRICKS)); + public static final Item INFESTED_DEEPSLATE = register(new BlockItem(builder(), Blocks.INFESTED_DEEPSLATE)); + public static final Item STONE_BRICKS = register(new BlockItem(builder(), Blocks.STONE_BRICKS)); + public static final Item MOSSY_STONE_BRICKS = register(new BlockItem(builder(), Blocks.MOSSY_STONE_BRICKS)); + public static final Item CRACKED_STONE_BRICKS = register(new BlockItem(builder(), Blocks.CRACKED_STONE_BRICKS)); + public static final Item CHISELED_STONE_BRICKS = register(new BlockItem(builder(), Blocks.CHISELED_STONE_BRICKS)); + public static final Item PACKED_MUD = register(new BlockItem(builder(), Blocks.PACKED_MUD)); + public static final Item MUD_BRICKS = register(new BlockItem(builder(), Blocks.MUD_BRICKS)); + public static final Item DEEPSLATE_BRICKS = register(new BlockItem(builder(), Blocks.DEEPSLATE_BRICKS)); + public static final Item CRACKED_DEEPSLATE_BRICKS = register(new BlockItem(builder(), Blocks.CRACKED_DEEPSLATE_BRICKS)); + public static final Item DEEPSLATE_TILES = register(new BlockItem(builder(), Blocks.DEEPSLATE_TILES)); + public static final Item CRACKED_DEEPSLATE_TILES = register(new BlockItem(builder(), Blocks.CRACKED_DEEPSLATE_TILES)); + public static final Item CHISELED_DEEPSLATE = register(new BlockItem(builder(), Blocks.CHISELED_DEEPSLATE)); + public static final Item REINFORCED_DEEPSLATE = register(new BlockItem(builder(), Blocks.REINFORCED_DEEPSLATE)); + public static final Item BROWN_MUSHROOM_BLOCK = register(new BlockItem(builder(), Blocks.BROWN_MUSHROOM_BLOCK)); + public static final Item RED_MUSHROOM_BLOCK = register(new BlockItem(builder(), Blocks.RED_MUSHROOM_BLOCK)); + public static final Item MUSHROOM_STEM = register(new BlockItem(builder(), Blocks.MUSHROOM_STEM)); + public static final Item IRON_BARS = register(new BlockItem(builder(), Blocks.IRON_BARS)); + public static final Item CHAIN = register(new BlockItem(builder(), Blocks.CHAIN)); + public static final Item GLASS_PANE = register(new BlockItem(builder(), Blocks.GLASS_PANE)); + public static final Item MELON = register(new BlockItem(builder(), Blocks.MELON)); + public static final Item VINE = register(new BlockItem(builder(), Blocks.VINE)); + public static final Item GLOW_LICHEN = register(new BlockItem(builder(), Blocks.GLOW_LICHEN)); + public static final Item BRICK_STAIRS = register(new BlockItem(builder(), Blocks.BRICK_STAIRS)); + public static final Item STONE_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.STONE_BRICK_STAIRS)); + public static final Item MUD_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.MUD_BRICK_STAIRS)); + public static final Item MYCELIUM = register(new BlockItem(builder(), Blocks.MYCELIUM)); + public static final Item LILY_PAD = register(new BlockItem(builder(), Blocks.LILY_PAD)); + public static final Item NETHER_BRICKS = register(new BlockItem(builder(), Blocks.NETHER_BRICKS)); + public static final Item CRACKED_NETHER_BRICKS = register(new BlockItem(builder(), Blocks.CRACKED_NETHER_BRICKS)); + public static final Item CHISELED_NETHER_BRICKS = register(new BlockItem(builder(), Blocks.CHISELED_NETHER_BRICKS)); + public static final Item NETHER_BRICK_FENCE = register(new BlockItem(builder(), Blocks.NETHER_BRICK_FENCE)); + public static final Item NETHER_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.NETHER_BRICK_STAIRS)); + public static final Item SCULK = register(new BlockItem(builder(), Blocks.SCULK)); + public static final Item SCULK_VEIN = register(new BlockItem(builder(), Blocks.SCULK_VEIN)); + public static final Item SCULK_CATALYST = register(new BlockItem(builder(), Blocks.SCULK_CATALYST)); + public static final Item SCULK_SHRIEKER = register(new BlockItem(builder(), Blocks.SCULK_SHRIEKER)); + public static final Item ENCHANTING_TABLE = register(new BlockItem(builder(), Blocks.ENCHANTING_TABLE)); + public static final Item END_PORTAL_FRAME = register(new BlockItem(builder(), Blocks.END_PORTAL_FRAME)); + public static final Item END_STONE = register(new BlockItem(builder(), Blocks.END_STONE)); + public static final Item END_STONE_BRICKS = register(new BlockItem(builder(), Blocks.END_STONE_BRICKS)); + public static final Item DRAGON_EGG = register(new BlockItem(builder(), Blocks.DRAGON_EGG)); + public static final Item SANDSTONE_STAIRS = register(new BlockItem(builder(), Blocks.SANDSTONE_STAIRS)); + public static final Item ENDER_CHEST = register(new BlockItem(builder(), Blocks.ENDER_CHEST)); + public static final Item EMERALD_BLOCK = register(new BlockItem(builder(), Blocks.EMERALD_BLOCK)); + public static final Item OAK_STAIRS = register(new BlockItem(builder(), Blocks.OAK_STAIRS)); + public static final Item SPRUCE_STAIRS = register(new BlockItem(builder(), Blocks.SPRUCE_STAIRS)); + public static final Item BIRCH_STAIRS = register(new BlockItem(builder(), Blocks.BIRCH_STAIRS)); + public static final Item JUNGLE_STAIRS = register(new BlockItem(builder(), Blocks.JUNGLE_STAIRS)); + public static final Item ACACIA_STAIRS = register(new BlockItem(builder(), Blocks.ACACIA_STAIRS)); + public static final Item CHERRY_STAIRS = register(new BlockItem(builder(), Blocks.CHERRY_STAIRS)); + public static final Item DARK_OAK_STAIRS = register(new BlockItem(builder(), Blocks.DARK_OAK_STAIRS)); + public static final Item MANGROVE_STAIRS = register(new BlockItem(builder(), Blocks.MANGROVE_STAIRS)); + public static final Item BAMBOO_STAIRS = register(new BlockItem(builder(), Blocks.BAMBOO_STAIRS)); + public static final Item BAMBOO_MOSAIC_STAIRS = register(new BlockItem(builder(), Blocks.BAMBOO_MOSAIC_STAIRS)); + public static final Item CRIMSON_STAIRS = register(new BlockItem(builder(), Blocks.CRIMSON_STAIRS)); + public static final Item WARPED_STAIRS = register(new BlockItem(builder(), Blocks.WARPED_STAIRS)); + public static final Item COMMAND_BLOCK = register(new BlockItem(builder(), Blocks.COMMAND_BLOCK)); + public static final Item BEACON = register(new BlockItem(builder(), Blocks.BEACON)); + public static final Item COBBLESTONE_WALL = register(new BlockItem(builder(), Blocks.COBBLESTONE_WALL)); + public static final Item MOSSY_COBBLESTONE_WALL = register(new BlockItem(builder(), Blocks.MOSSY_COBBLESTONE_WALL)); + public static final Item BRICK_WALL = register(new BlockItem(builder(), Blocks.BRICK_WALL)); + public static final Item PRISMARINE_WALL = register(new BlockItem(builder(), Blocks.PRISMARINE_WALL)); + public static final Item RED_SANDSTONE_WALL = register(new BlockItem(builder(), Blocks.RED_SANDSTONE_WALL)); + public static final Item MOSSY_STONE_BRICK_WALL = register(new BlockItem(builder(), Blocks.MOSSY_STONE_BRICK_WALL)); + public static final Item GRANITE_WALL = register(new BlockItem(builder(), Blocks.GRANITE_WALL)); + public static final Item STONE_BRICK_WALL = register(new BlockItem(builder(), Blocks.STONE_BRICK_WALL)); + public static final Item MUD_BRICK_WALL = register(new BlockItem(builder(), Blocks.MUD_BRICK_WALL)); + public static final Item NETHER_BRICK_WALL = register(new BlockItem(builder(), Blocks.NETHER_BRICK_WALL)); + public static final Item ANDESITE_WALL = register(new BlockItem(builder(), Blocks.ANDESITE_WALL)); + public static final Item RED_NETHER_BRICK_WALL = register(new BlockItem(builder(), Blocks.RED_NETHER_BRICK_WALL)); + public static final Item SANDSTONE_WALL = register(new BlockItem(builder(), Blocks.SANDSTONE_WALL)); + public static final Item END_STONE_BRICK_WALL = register(new BlockItem(builder(), Blocks.END_STONE_BRICK_WALL)); + public static final Item DIORITE_WALL = register(new BlockItem(builder(), Blocks.DIORITE_WALL)); + public static final Item BLACKSTONE_WALL = register(new BlockItem(builder(), Blocks.BLACKSTONE_WALL)); + public static final Item POLISHED_BLACKSTONE_WALL = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_WALL)); + public static final Item POLISHED_BLACKSTONE_BRICK_WALL = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_BRICK_WALL)); + public static final Item COBBLED_DEEPSLATE_WALL = register(new BlockItem(builder(), Blocks.COBBLED_DEEPSLATE_WALL)); + public static final Item POLISHED_DEEPSLATE_WALL = register(new BlockItem(builder(), Blocks.POLISHED_DEEPSLATE_WALL)); + public static final Item DEEPSLATE_BRICK_WALL = register(new BlockItem(builder(), Blocks.DEEPSLATE_BRICK_WALL)); + public static final Item DEEPSLATE_TILE_WALL = register(new BlockItem(builder(), Blocks.DEEPSLATE_TILE_WALL)); + public static final Item ANVIL = register(new BlockItem(builder(), Blocks.ANVIL)); + public static final Item CHIPPED_ANVIL = register(new BlockItem(builder(), Blocks.CHIPPED_ANVIL)); + public static final Item DAMAGED_ANVIL = register(new BlockItem(builder(), Blocks.DAMAGED_ANVIL)); + public static final Item CHISELED_QUARTZ_BLOCK = register(new BlockItem(builder(), Blocks.CHISELED_QUARTZ_BLOCK)); + public static final Item QUARTZ_BLOCK = register(new BlockItem(builder(), Blocks.QUARTZ_BLOCK)); + public static final Item QUARTZ_BRICKS = register(new BlockItem(builder(), Blocks.QUARTZ_BRICKS)); + public static final Item QUARTZ_PILLAR = register(new BlockItem(builder(), Blocks.QUARTZ_PILLAR)); + public static final Item QUARTZ_STAIRS = register(new BlockItem(builder(), Blocks.QUARTZ_STAIRS)); + public static final Item WHITE_TERRACOTTA = register(new BlockItem(builder(), Blocks.WHITE_TERRACOTTA)); + public static final Item ORANGE_TERRACOTTA = register(new BlockItem(builder(), Blocks.ORANGE_TERRACOTTA)); + public static final Item MAGENTA_TERRACOTTA = register(new BlockItem(builder(), Blocks.MAGENTA_TERRACOTTA)); + public static final Item LIGHT_BLUE_TERRACOTTA = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_TERRACOTTA)); + public static final Item YELLOW_TERRACOTTA = register(new BlockItem(builder(), Blocks.YELLOW_TERRACOTTA)); + public static final Item LIME_TERRACOTTA = register(new BlockItem(builder(), Blocks.LIME_TERRACOTTA)); + public static final Item PINK_TERRACOTTA = register(new BlockItem(builder(), Blocks.PINK_TERRACOTTA)); + public static final Item GRAY_TERRACOTTA = register(new BlockItem(builder(), Blocks.GRAY_TERRACOTTA)); + public static final Item LIGHT_GRAY_TERRACOTTA = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_TERRACOTTA)); + public static final Item CYAN_TERRACOTTA = register(new BlockItem(builder(), Blocks.CYAN_TERRACOTTA)); + public static final Item PURPLE_TERRACOTTA = register(new BlockItem(builder(), Blocks.PURPLE_TERRACOTTA)); + public static final Item BLUE_TERRACOTTA = register(new BlockItem(builder(), Blocks.BLUE_TERRACOTTA)); + public static final Item BROWN_TERRACOTTA = register(new BlockItem(builder(), Blocks.BROWN_TERRACOTTA)); + public static final Item GREEN_TERRACOTTA = register(new BlockItem(builder(), Blocks.GREEN_TERRACOTTA)); + public static final Item RED_TERRACOTTA = register(new BlockItem(builder(), Blocks.RED_TERRACOTTA)); + public static final Item BLACK_TERRACOTTA = register(new BlockItem(builder(), Blocks.BLACK_TERRACOTTA)); + public static final Item BARRIER = register(new BlockItem(builder(), Blocks.BARRIER)); + public static final Item LIGHT = register(new BlockItem(builder(), Blocks.LIGHT)); + public static final Item HAY_BLOCK = register(new BlockItem(builder(), Blocks.HAY_BLOCK)); + public static final Item WHITE_CARPET = register(new BlockItem(builder(), Blocks.WHITE_CARPET)); + public static final Item ORANGE_CARPET = register(new BlockItem(builder(), Blocks.ORANGE_CARPET)); + public static final Item MAGENTA_CARPET = register(new BlockItem(builder(), Blocks.MAGENTA_CARPET)); + public static final Item LIGHT_BLUE_CARPET = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_CARPET)); + public static final Item YELLOW_CARPET = register(new BlockItem(builder(), Blocks.YELLOW_CARPET)); + public static final Item LIME_CARPET = register(new BlockItem(builder(), Blocks.LIME_CARPET)); + public static final Item PINK_CARPET = register(new BlockItem(builder(), Blocks.PINK_CARPET)); + public static final Item GRAY_CARPET = register(new BlockItem(builder(), Blocks.GRAY_CARPET)); + public static final Item LIGHT_GRAY_CARPET = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_CARPET)); + public static final Item CYAN_CARPET = register(new BlockItem(builder(), Blocks.CYAN_CARPET)); + public static final Item PURPLE_CARPET = register(new BlockItem(builder(), Blocks.PURPLE_CARPET)); + public static final Item BLUE_CARPET = register(new BlockItem(builder(), Blocks.BLUE_CARPET)); + public static final Item BROWN_CARPET = register(new BlockItem(builder(), Blocks.BROWN_CARPET)); + public static final Item GREEN_CARPET = register(new BlockItem(builder(), Blocks.GREEN_CARPET)); + public static final Item RED_CARPET = register(new BlockItem(builder(), Blocks.RED_CARPET)); + public static final Item BLACK_CARPET = register(new BlockItem(builder(), Blocks.BLACK_CARPET)); + public static final Item TERRACOTTA = register(new BlockItem(builder(), Blocks.TERRACOTTA)); + public static final Item PACKED_ICE = register(new BlockItem(builder(), Blocks.PACKED_ICE)); + public static final Item DIRT_PATH = register(new BlockItem(builder(), Blocks.DIRT_PATH)); + public static final Item SUNFLOWER = register(new BlockItem(builder(), Blocks.SUNFLOWER)); + public static final Item LILAC = register(new BlockItem(builder(), Blocks.LILAC)); + public static final Item ROSE_BUSH = register(new BlockItem(builder(), Blocks.ROSE_BUSH)); + public static final Item PEONY = register(new BlockItem(builder(), Blocks.PEONY)); + public static final Item TALL_GRASS = register(new BlockItem(builder(), Blocks.TALL_GRASS)); + public static final Item LARGE_FERN = register(new BlockItem(builder(), Blocks.LARGE_FERN)); + public static final Item WHITE_STAINED_GLASS = register(new BlockItem(builder(), Blocks.WHITE_STAINED_GLASS)); + public static final Item ORANGE_STAINED_GLASS = register(new BlockItem(builder(), Blocks.ORANGE_STAINED_GLASS)); + public static final Item MAGENTA_STAINED_GLASS = register(new BlockItem(builder(), Blocks.MAGENTA_STAINED_GLASS)); + public static final Item LIGHT_BLUE_STAINED_GLASS = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_STAINED_GLASS)); + public static final Item YELLOW_STAINED_GLASS = register(new BlockItem(builder(), Blocks.YELLOW_STAINED_GLASS)); + public static final Item LIME_STAINED_GLASS = register(new BlockItem(builder(), Blocks.LIME_STAINED_GLASS)); + public static final Item PINK_STAINED_GLASS = register(new BlockItem(builder(), Blocks.PINK_STAINED_GLASS)); + public static final Item GRAY_STAINED_GLASS = register(new BlockItem(builder(), Blocks.GRAY_STAINED_GLASS)); + public static final Item LIGHT_GRAY_STAINED_GLASS = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_STAINED_GLASS)); + public static final Item CYAN_STAINED_GLASS = register(new BlockItem(builder(), Blocks.CYAN_STAINED_GLASS)); + public static final Item PURPLE_STAINED_GLASS = register(new BlockItem(builder(), Blocks.PURPLE_STAINED_GLASS)); + public static final Item BLUE_STAINED_GLASS = register(new BlockItem(builder(), Blocks.BLUE_STAINED_GLASS)); + public static final Item BROWN_STAINED_GLASS = register(new BlockItem(builder(), Blocks.BROWN_STAINED_GLASS)); + public static final Item GREEN_STAINED_GLASS = register(new BlockItem(builder(), Blocks.GREEN_STAINED_GLASS)); + public static final Item RED_STAINED_GLASS = register(new BlockItem(builder(), Blocks.RED_STAINED_GLASS)); + public static final Item BLACK_STAINED_GLASS = register(new BlockItem(builder(), Blocks.BLACK_STAINED_GLASS)); + public static final Item WHITE_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.WHITE_STAINED_GLASS_PANE)); + public static final Item ORANGE_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.ORANGE_STAINED_GLASS_PANE)); + public static final Item MAGENTA_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.MAGENTA_STAINED_GLASS_PANE)); + public static final Item LIGHT_BLUE_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_STAINED_GLASS_PANE)); + public static final Item YELLOW_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.YELLOW_STAINED_GLASS_PANE)); + public static final Item LIME_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.LIME_STAINED_GLASS_PANE)); + public static final Item PINK_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.PINK_STAINED_GLASS_PANE)); + public static final Item GRAY_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.GRAY_STAINED_GLASS_PANE)); + public static final Item LIGHT_GRAY_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_STAINED_GLASS_PANE)); + public static final Item CYAN_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.CYAN_STAINED_GLASS_PANE)); + public static final Item PURPLE_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.PURPLE_STAINED_GLASS_PANE)); + public static final Item BLUE_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.BLUE_STAINED_GLASS_PANE)); + public static final Item BROWN_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.BROWN_STAINED_GLASS_PANE)); + public static final Item GREEN_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.GREEN_STAINED_GLASS_PANE)); + public static final Item RED_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.RED_STAINED_GLASS_PANE)); + public static final Item BLACK_STAINED_GLASS_PANE = register(new BlockItem(builder(), Blocks.BLACK_STAINED_GLASS_PANE)); + public static final Item PRISMARINE = register(new BlockItem(builder(), Blocks.PRISMARINE)); + public static final Item PRISMARINE_BRICKS = register(new BlockItem(builder(), Blocks.PRISMARINE_BRICKS)); + public static final Item DARK_PRISMARINE = register(new BlockItem(builder(), Blocks.DARK_PRISMARINE)); + public static final Item PRISMARINE_STAIRS = register(new BlockItem(builder(), Blocks.PRISMARINE_STAIRS)); + public static final Item PRISMARINE_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.PRISMARINE_BRICK_STAIRS)); + public static final Item DARK_PRISMARINE_STAIRS = register(new BlockItem(builder(), Blocks.DARK_PRISMARINE_STAIRS)); + public static final Item SEA_LANTERN = register(new BlockItem(builder(), Blocks.SEA_LANTERN)); + public static final Item RED_SANDSTONE = register(new BlockItem(builder(), Blocks.RED_SANDSTONE)); + public static final Item CHISELED_RED_SANDSTONE = register(new BlockItem(builder(), Blocks.CHISELED_RED_SANDSTONE)); + public static final Item CUT_RED_SANDSTONE = register(new BlockItem(builder(), Blocks.CUT_RED_SANDSTONE)); + public static final Item RED_SANDSTONE_STAIRS = register(new BlockItem(builder(), Blocks.RED_SANDSTONE_STAIRS)); + public static final Item REPEATING_COMMAND_BLOCK = register(new BlockItem(builder(), Blocks.REPEATING_COMMAND_BLOCK)); + public static final Item CHAIN_COMMAND_BLOCK = register(new BlockItem(builder(), Blocks.CHAIN_COMMAND_BLOCK)); + public static final Item MAGMA_BLOCK = register(new BlockItem(builder(), Blocks.MAGMA_BLOCK)); + public static final Item NETHER_WART_BLOCK = register(new BlockItem(builder(), Blocks.NETHER_WART_BLOCK)); + public static final Item WARPED_WART_BLOCK = register(new BlockItem(builder(), Blocks.WARPED_WART_BLOCK)); + public static final Item RED_NETHER_BRICKS = register(new BlockItem(builder(), Blocks.RED_NETHER_BRICKS)); + public static final Item BONE_BLOCK = register(new BlockItem(builder(), Blocks.BONE_BLOCK)); + public static final Item STRUCTURE_VOID = register(new BlockItem(builder(), Blocks.STRUCTURE_VOID)); + public static final Item SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.SHULKER_BOX)); + public static final Item WHITE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.WHITE_SHULKER_BOX)); + public static final Item ORANGE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.ORANGE_SHULKER_BOX)); + public static final Item MAGENTA_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.MAGENTA_SHULKER_BOX)); + public static final Item LIGHT_BLUE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.LIGHT_BLUE_SHULKER_BOX)); + public static final Item YELLOW_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.YELLOW_SHULKER_BOX)); + public static final Item LIME_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.LIME_SHULKER_BOX)); + public static final Item PINK_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.PINK_SHULKER_BOX)); + public static final Item GRAY_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.GRAY_SHULKER_BOX)); + public static final Item LIGHT_GRAY_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.LIGHT_GRAY_SHULKER_BOX)); + public static final Item CYAN_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.CYAN_SHULKER_BOX)); + public static final Item PURPLE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.PURPLE_SHULKER_BOX)); + public static final Item BLUE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.BLUE_SHULKER_BOX)); + public static final Item BROWN_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.BROWN_SHULKER_BOX)); + public static final Item GREEN_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.GREEN_SHULKER_BOX)); + public static final Item RED_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.RED_SHULKER_BOX)); + public static final Item BLACK_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.BLACK_SHULKER_BOX)); + public static final Item WHITE_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.WHITE_GLAZED_TERRACOTTA)); + public static final Item ORANGE_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.ORANGE_GLAZED_TERRACOTTA)); + public static final Item MAGENTA_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.MAGENTA_GLAZED_TERRACOTTA)); + public static final Item LIGHT_BLUE_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_GLAZED_TERRACOTTA)); + public static final Item YELLOW_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.YELLOW_GLAZED_TERRACOTTA)); + public static final Item LIME_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.LIME_GLAZED_TERRACOTTA)); + public static final Item PINK_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.PINK_GLAZED_TERRACOTTA)); + public static final Item GRAY_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.GRAY_GLAZED_TERRACOTTA)); + public static final Item LIGHT_GRAY_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_GLAZED_TERRACOTTA)); + public static final Item CYAN_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.CYAN_GLAZED_TERRACOTTA)); + public static final Item PURPLE_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.PURPLE_GLAZED_TERRACOTTA)); + public static final Item BLUE_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.BLUE_GLAZED_TERRACOTTA)); + public static final Item BROWN_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.BROWN_GLAZED_TERRACOTTA)); + public static final Item GREEN_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.GREEN_GLAZED_TERRACOTTA)); + public static final Item RED_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.RED_GLAZED_TERRACOTTA)); + public static final Item BLACK_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.BLACK_GLAZED_TERRACOTTA)); + public static final Item WHITE_CONCRETE = register(new BlockItem(builder(), Blocks.WHITE_CONCRETE)); + public static final Item ORANGE_CONCRETE = register(new BlockItem(builder(), Blocks.ORANGE_CONCRETE)); + public static final Item MAGENTA_CONCRETE = register(new BlockItem(builder(), Blocks.MAGENTA_CONCRETE)); + public static final Item LIGHT_BLUE_CONCRETE = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_CONCRETE)); + public static final Item YELLOW_CONCRETE = register(new BlockItem(builder(), Blocks.YELLOW_CONCRETE)); + public static final Item LIME_CONCRETE = register(new BlockItem(builder(), Blocks.LIME_CONCRETE)); + public static final Item PINK_CONCRETE = register(new BlockItem(builder(), Blocks.PINK_CONCRETE)); + public static final Item GRAY_CONCRETE = register(new BlockItem(builder(), Blocks.GRAY_CONCRETE)); + public static final Item LIGHT_GRAY_CONCRETE = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_CONCRETE)); + public static final Item CYAN_CONCRETE = register(new BlockItem(builder(), Blocks.CYAN_CONCRETE)); + public static final Item PURPLE_CONCRETE = register(new BlockItem(builder(), Blocks.PURPLE_CONCRETE)); + public static final Item BLUE_CONCRETE = register(new BlockItem(builder(), Blocks.BLUE_CONCRETE)); + public static final Item BROWN_CONCRETE = register(new BlockItem(builder(), Blocks.BROWN_CONCRETE)); + public static final Item GREEN_CONCRETE = register(new BlockItem(builder(), Blocks.GREEN_CONCRETE)); + public static final Item RED_CONCRETE = register(new BlockItem(builder(), Blocks.RED_CONCRETE)); + public static final Item BLACK_CONCRETE = register(new BlockItem(builder(), Blocks.BLACK_CONCRETE)); + public static final Item WHITE_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.WHITE_CONCRETE_POWDER)); + public static final Item ORANGE_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.ORANGE_CONCRETE_POWDER)); + public static final Item MAGENTA_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.MAGENTA_CONCRETE_POWDER)); + public static final Item LIGHT_BLUE_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_CONCRETE_POWDER)); + public static final Item YELLOW_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.YELLOW_CONCRETE_POWDER)); + public static final Item LIME_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.LIME_CONCRETE_POWDER)); + public static final Item PINK_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.PINK_CONCRETE_POWDER)); + public static final Item GRAY_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.GRAY_CONCRETE_POWDER)); + public static final Item LIGHT_GRAY_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_CONCRETE_POWDER)); + public static final Item CYAN_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.CYAN_CONCRETE_POWDER)); + public static final Item PURPLE_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.PURPLE_CONCRETE_POWDER)); + public static final Item BLUE_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.BLUE_CONCRETE_POWDER)); + public static final Item BROWN_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.BROWN_CONCRETE_POWDER)); + public static final Item GREEN_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.GREEN_CONCRETE_POWDER)); + public static final Item RED_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.RED_CONCRETE_POWDER)); + public static final Item BLACK_CONCRETE_POWDER = register(new BlockItem(builder(), Blocks.BLACK_CONCRETE_POWDER)); + public static final Item TURTLE_EGG = register(new BlockItem(builder(), Blocks.TURTLE_EGG)); + public static final Item SNIFFER_EGG = register(new BlockItem(builder(), Blocks.SNIFFER_EGG)); + public static final Item DEAD_TUBE_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.DEAD_TUBE_CORAL_BLOCK)); + public static final Item DEAD_BRAIN_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.DEAD_BRAIN_CORAL_BLOCK)); + public static final Item DEAD_BUBBLE_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.DEAD_BUBBLE_CORAL_BLOCK)); + public static final Item DEAD_FIRE_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.DEAD_FIRE_CORAL_BLOCK)); + public static final Item DEAD_HORN_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.DEAD_HORN_CORAL_BLOCK)); + public static final Item TUBE_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.TUBE_CORAL_BLOCK)); + public static final Item BRAIN_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.BRAIN_CORAL_BLOCK)); + public static final Item BUBBLE_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.BUBBLE_CORAL_BLOCK)); + public static final Item FIRE_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.FIRE_CORAL_BLOCK)); + public static final Item HORN_CORAL_BLOCK = register(new BlockItem(builder(), Blocks.HORN_CORAL_BLOCK)); + public static final Item TUBE_CORAL = register(new BlockItem(builder(), Blocks.TUBE_CORAL)); + public static final Item BRAIN_CORAL = register(new BlockItem(builder(), Blocks.BRAIN_CORAL)); + public static final Item BUBBLE_CORAL = register(new BlockItem(builder(), Blocks.BUBBLE_CORAL)); + public static final Item FIRE_CORAL = register(new BlockItem(builder(), Blocks.FIRE_CORAL)); + public static final Item HORN_CORAL = register(new BlockItem(builder(), Blocks.HORN_CORAL)); + public static final Item DEAD_BRAIN_CORAL = register(new BlockItem(builder(), Blocks.DEAD_BRAIN_CORAL)); + public static final Item DEAD_BUBBLE_CORAL = register(new BlockItem(builder(), Blocks.DEAD_BUBBLE_CORAL)); + public static final Item DEAD_FIRE_CORAL = register(new BlockItem(builder(), Blocks.DEAD_FIRE_CORAL)); + public static final Item DEAD_HORN_CORAL = register(new BlockItem(builder(), Blocks.DEAD_HORN_CORAL)); + public static final Item DEAD_TUBE_CORAL = register(new BlockItem(builder(), Blocks.DEAD_TUBE_CORAL)); + public static final Item TUBE_CORAL_FAN = register(new BlockItem(builder(), Blocks.TUBE_CORAL_FAN, Blocks.TUBE_CORAL_WALL_FAN)); + public static final Item BRAIN_CORAL_FAN = register(new BlockItem(builder(), Blocks.BRAIN_CORAL_FAN, Blocks.BRAIN_CORAL_WALL_FAN)); + public static final Item BUBBLE_CORAL_FAN = register(new BlockItem(builder(), Blocks.BUBBLE_CORAL_FAN, Blocks.BUBBLE_CORAL_WALL_FAN)); + public static final Item FIRE_CORAL_FAN = register(new BlockItem(builder(), Blocks.FIRE_CORAL_FAN, Blocks.FIRE_CORAL_WALL_FAN)); + public static final Item HORN_CORAL_FAN = register(new BlockItem(builder(), Blocks.HORN_CORAL_FAN, Blocks.HORN_CORAL_WALL_FAN)); + public static final Item DEAD_TUBE_CORAL_FAN = register(new BlockItem(builder(), Blocks.DEAD_TUBE_CORAL_FAN, Blocks.DEAD_TUBE_CORAL_WALL_FAN)); + public static final Item DEAD_BRAIN_CORAL_FAN = register(new BlockItem(builder(), Blocks.DEAD_BRAIN_CORAL_FAN, Blocks.DEAD_BRAIN_CORAL_WALL_FAN)); + public static final Item DEAD_BUBBLE_CORAL_FAN = register(new BlockItem(builder(), Blocks.DEAD_BUBBLE_CORAL_FAN, Blocks.DEAD_BUBBLE_CORAL_WALL_FAN)); + public static final Item DEAD_FIRE_CORAL_FAN = register(new BlockItem(builder(), Blocks.DEAD_FIRE_CORAL_FAN, Blocks.DEAD_FIRE_CORAL_WALL_FAN)); + public static final Item DEAD_HORN_CORAL_FAN = register(new BlockItem(builder(), Blocks.DEAD_HORN_CORAL_FAN, Blocks.DEAD_HORN_CORAL_WALL_FAN)); + public static final Item BLUE_ICE = register(new BlockItem(builder(), Blocks.BLUE_ICE)); + public static final Item CONDUIT = register(new BlockItem(builder(), Blocks.CONDUIT)); + public static final Item POLISHED_GRANITE_STAIRS = register(new BlockItem(builder(), Blocks.POLISHED_GRANITE_STAIRS)); + public static final Item SMOOTH_RED_SANDSTONE_STAIRS = register(new BlockItem(builder(), Blocks.SMOOTH_RED_SANDSTONE_STAIRS)); + public static final Item MOSSY_STONE_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.MOSSY_STONE_BRICK_STAIRS)); + public static final Item POLISHED_DIORITE_STAIRS = register(new BlockItem(builder(), Blocks.POLISHED_DIORITE_STAIRS)); + public static final Item MOSSY_COBBLESTONE_STAIRS = register(new BlockItem(builder(), Blocks.MOSSY_COBBLESTONE_STAIRS)); + public static final Item END_STONE_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.END_STONE_BRICK_STAIRS)); + public static final Item STONE_STAIRS = register(new BlockItem(builder(), Blocks.STONE_STAIRS)); + public static final Item SMOOTH_SANDSTONE_STAIRS = register(new BlockItem(builder(), Blocks.SMOOTH_SANDSTONE_STAIRS)); + public static final Item SMOOTH_QUARTZ_STAIRS = register(new BlockItem(builder(), Blocks.SMOOTH_QUARTZ_STAIRS)); + public static final Item GRANITE_STAIRS = register(new BlockItem(builder(), Blocks.GRANITE_STAIRS)); + public static final Item ANDESITE_STAIRS = register(new BlockItem(builder(), Blocks.ANDESITE_STAIRS)); + public static final Item RED_NETHER_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.RED_NETHER_BRICK_STAIRS)); + public static final Item POLISHED_ANDESITE_STAIRS = register(new BlockItem(builder(), Blocks.POLISHED_ANDESITE_STAIRS)); + public static final Item DIORITE_STAIRS = register(new BlockItem(builder(), Blocks.DIORITE_STAIRS)); + public static final Item COBBLED_DEEPSLATE_STAIRS = register(new BlockItem(builder(), Blocks.COBBLED_DEEPSLATE_STAIRS)); + public static final Item POLISHED_DEEPSLATE_STAIRS = register(new BlockItem(builder(), Blocks.POLISHED_DEEPSLATE_STAIRS)); + public static final Item DEEPSLATE_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.DEEPSLATE_BRICK_STAIRS)); + public static final Item DEEPSLATE_TILE_STAIRS = register(new BlockItem(builder(), Blocks.DEEPSLATE_TILE_STAIRS)); + public static final Item POLISHED_GRANITE_SLAB = register(new BlockItem(builder(), Blocks.POLISHED_GRANITE_SLAB)); + public static final Item SMOOTH_RED_SANDSTONE_SLAB = register(new BlockItem(builder(), Blocks.SMOOTH_RED_SANDSTONE_SLAB)); + public static final Item MOSSY_STONE_BRICK_SLAB = register(new BlockItem(builder(), Blocks.MOSSY_STONE_BRICK_SLAB)); + public static final Item POLISHED_DIORITE_SLAB = register(new BlockItem(builder(), Blocks.POLISHED_DIORITE_SLAB)); + public static final Item MOSSY_COBBLESTONE_SLAB = register(new BlockItem(builder(), Blocks.MOSSY_COBBLESTONE_SLAB)); + public static final Item END_STONE_BRICK_SLAB = register(new BlockItem(builder(), Blocks.END_STONE_BRICK_SLAB)); + public static final Item SMOOTH_SANDSTONE_SLAB = register(new BlockItem(builder(), Blocks.SMOOTH_SANDSTONE_SLAB)); + public static final Item SMOOTH_QUARTZ_SLAB = register(new BlockItem(builder(), Blocks.SMOOTH_QUARTZ_SLAB)); + public static final Item GRANITE_SLAB = register(new BlockItem(builder(), Blocks.GRANITE_SLAB)); + public static final Item ANDESITE_SLAB = register(new BlockItem(builder(), Blocks.ANDESITE_SLAB)); + public static final Item RED_NETHER_BRICK_SLAB = register(new BlockItem(builder(), Blocks.RED_NETHER_BRICK_SLAB)); + public static final Item POLISHED_ANDESITE_SLAB = register(new BlockItem(builder(), Blocks.POLISHED_ANDESITE_SLAB)); + public static final Item DIORITE_SLAB = register(new BlockItem(builder(), Blocks.DIORITE_SLAB)); + public static final Item COBBLED_DEEPSLATE_SLAB = register(new BlockItem(builder(), Blocks.COBBLED_DEEPSLATE_SLAB)); + public static final Item POLISHED_DEEPSLATE_SLAB = register(new BlockItem(builder(), Blocks.POLISHED_DEEPSLATE_SLAB)); + public static final Item DEEPSLATE_BRICK_SLAB = register(new BlockItem(builder(), Blocks.DEEPSLATE_BRICK_SLAB)); + public static final Item DEEPSLATE_TILE_SLAB = register(new BlockItem(builder(), Blocks.DEEPSLATE_TILE_SLAB)); + public static final Item SCAFFOLDING = register(new BlockItem(builder(), Blocks.SCAFFOLDING)); + public static final Item REDSTONE = register(new BlockItem("redstone", builder(), Blocks.REDSTONE_WIRE)); + public static final Item REDSTONE_TORCH = register(new BlockItem(builder(), Blocks.REDSTONE_TORCH, Blocks.REDSTONE_WALL_TORCH)); + public static final Item REDSTONE_BLOCK = register(new BlockItem(builder(), Blocks.REDSTONE_BLOCK)); + public static final Item REPEATER = register(new BlockItem(builder(), Blocks.REPEATER)); + public static final Item COMPARATOR = register(new BlockItem(builder(), Blocks.COMPARATOR)); + public static final Item PISTON = register(new BlockItem(builder(), Blocks.PISTON)); + public static final Item STICKY_PISTON = register(new BlockItem(builder(), Blocks.STICKY_PISTON)); + public static final Item SLIME_BLOCK = register(new BlockItem(builder(), Blocks.SLIME_BLOCK)); + public static final Item HONEY_BLOCK = register(new BlockItem(builder(), Blocks.HONEY_BLOCK)); + public static final Item OBSERVER = register(new BlockItem(builder(), Blocks.OBSERVER)); + public static final Item HOPPER = register(new BlockItem(builder(), Blocks.HOPPER)); + public static final Item DISPENSER = register(new BlockItem(builder(), Blocks.DISPENSER)); + public static final Item DROPPER = register(new BlockItem(builder(), Blocks.DROPPER)); + public static final Item LECTERN = register(new BlockItem(builder(), Blocks.LECTERN)); + public static final Item TARGET = register(new BlockItem(builder(), Blocks.TARGET)); + public static final Item LEVER = register(new BlockItem(builder(), Blocks.LEVER)); + public static final Item LIGHTNING_ROD = register(new BlockItem(builder(), Blocks.LIGHTNING_ROD)); + public static final Item DAYLIGHT_DETECTOR = register(new BlockItem(builder(), Blocks.DAYLIGHT_DETECTOR)); + public static final Item SCULK_SENSOR = register(new BlockItem(builder(), Blocks.SCULK_SENSOR)); + public static final Item CALIBRATED_SCULK_SENSOR = register(new BlockItem(builder(), Blocks.CALIBRATED_SCULK_SENSOR)); + public static final Item TRIPWIRE_HOOK = register(new BlockItem(builder(), Blocks.TRIPWIRE_HOOK)); + public static final Item TRAPPED_CHEST = register(new BlockItem(builder(), Blocks.TRAPPED_CHEST)); + public static final Item TNT = register(new BlockItem(builder(), Blocks.TNT)); + public static final Item REDSTONE_LAMP = register(new BlockItem(builder(), Blocks.REDSTONE_LAMP)); + public static final Item NOTE_BLOCK = register(new BlockItem(builder(), Blocks.NOTE_BLOCK)); + public static final Item STONE_BUTTON = register(new BlockItem(builder(), Blocks.STONE_BUTTON)); + public static final Item POLISHED_BLACKSTONE_BUTTON = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_BUTTON)); + public static final Item OAK_BUTTON = register(new BlockItem(builder(), Blocks.OAK_BUTTON)); + public static final Item SPRUCE_BUTTON = register(new BlockItem(builder(), Blocks.SPRUCE_BUTTON)); + public static final Item BIRCH_BUTTON = register(new BlockItem(builder(), Blocks.BIRCH_BUTTON)); + public static final Item JUNGLE_BUTTON = register(new BlockItem(builder(), Blocks.JUNGLE_BUTTON)); + public static final Item ACACIA_BUTTON = register(new BlockItem(builder(), Blocks.ACACIA_BUTTON)); + public static final Item CHERRY_BUTTON = register(new BlockItem(builder(), Blocks.CHERRY_BUTTON)); + public static final Item DARK_OAK_BUTTON = register(new BlockItem(builder(), Blocks.DARK_OAK_BUTTON)); + public static final Item MANGROVE_BUTTON = register(new BlockItem(builder(), Blocks.MANGROVE_BUTTON)); + public static final Item BAMBOO_BUTTON = register(new BlockItem(builder(), Blocks.BAMBOO_BUTTON)); + public static final Item CRIMSON_BUTTON = register(new BlockItem(builder(), Blocks.CRIMSON_BUTTON)); + public static final Item WARPED_BUTTON = register(new BlockItem(builder(), Blocks.WARPED_BUTTON)); + public static final Item STONE_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.STONE_PRESSURE_PLATE)); + public static final Item POLISHED_BLACKSTONE_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_PRESSURE_PLATE)); + public static final Item LIGHT_WEIGHTED_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.LIGHT_WEIGHTED_PRESSURE_PLATE)); + public static final Item HEAVY_WEIGHTED_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.HEAVY_WEIGHTED_PRESSURE_PLATE)); + public static final Item OAK_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.OAK_PRESSURE_PLATE)); + public static final Item SPRUCE_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.SPRUCE_PRESSURE_PLATE)); + public static final Item BIRCH_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.BIRCH_PRESSURE_PLATE)); + public static final Item JUNGLE_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.JUNGLE_PRESSURE_PLATE)); + public static final Item ACACIA_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.ACACIA_PRESSURE_PLATE)); + public static final Item CHERRY_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.CHERRY_PRESSURE_PLATE)); + public static final Item DARK_OAK_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.DARK_OAK_PRESSURE_PLATE)); + public static final Item MANGROVE_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.MANGROVE_PRESSURE_PLATE)); + public static final Item BAMBOO_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.BAMBOO_PRESSURE_PLATE)); + public static final Item CRIMSON_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.CRIMSON_PRESSURE_PLATE)); + public static final Item WARPED_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.WARPED_PRESSURE_PLATE)); + public static final Item IRON_DOOR = register(new BlockItem(builder(), Blocks.IRON_DOOR)); + public static final Item OAK_DOOR = register(new BlockItem(builder(), Blocks.OAK_DOOR)); + public static final Item SPRUCE_DOOR = register(new BlockItem(builder(), Blocks.SPRUCE_DOOR)); + public static final Item BIRCH_DOOR = register(new BlockItem(builder(), Blocks.BIRCH_DOOR)); + public static final Item JUNGLE_DOOR = register(new BlockItem(builder(), Blocks.JUNGLE_DOOR)); + public static final Item ACACIA_DOOR = register(new BlockItem(builder(), Blocks.ACACIA_DOOR)); + public static final Item CHERRY_DOOR = register(new BlockItem(builder(), Blocks.CHERRY_DOOR)); + public static final Item DARK_OAK_DOOR = register(new BlockItem(builder(), Blocks.DARK_OAK_DOOR)); + public static final Item MANGROVE_DOOR = register(new BlockItem(builder(), Blocks.MANGROVE_DOOR)); + public static final Item BAMBOO_DOOR = register(new BlockItem(builder(), Blocks.BAMBOO_DOOR)); + public static final Item CRIMSON_DOOR = register(new BlockItem(builder(), Blocks.CRIMSON_DOOR)); + public static final Item WARPED_DOOR = register(new BlockItem(builder(), Blocks.WARPED_DOOR)); + public static final Item COPPER_DOOR = register(new BlockItem(builder(), Blocks.COPPER_DOOR)); + public static final Item EXPOSED_COPPER_DOOR = register(new BlockItem(builder(), Blocks.EXPOSED_COPPER_DOOR)); + public static final Item WEATHERED_COPPER_DOOR = register(new BlockItem(builder(), Blocks.WEATHERED_COPPER_DOOR)); + public static final Item OXIDIZED_COPPER_DOOR = register(new BlockItem(builder(), Blocks.OXIDIZED_COPPER_DOOR)); + public static final Item WAXED_COPPER_DOOR = register(new BlockItem(builder(), Blocks.WAXED_COPPER_DOOR)); + public static final Item WAXED_EXPOSED_COPPER_DOOR = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_COPPER_DOOR)); + public static final Item WAXED_WEATHERED_COPPER_DOOR = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_COPPER_DOOR)); + public static final Item WAXED_OXIDIZED_COPPER_DOOR = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_COPPER_DOOR)); + public static final Item IRON_TRAPDOOR = register(new BlockItem(builder(), Blocks.IRON_TRAPDOOR)); + public static final Item OAK_TRAPDOOR = register(new BlockItem(builder(), Blocks.OAK_TRAPDOOR)); + public static final Item SPRUCE_TRAPDOOR = register(new BlockItem(builder(), Blocks.SPRUCE_TRAPDOOR)); + public static final Item BIRCH_TRAPDOOR = register(new BlockItem(builder(), Blocks.BIRCH_TRAPDOOR)); + public static final Item JUNGLE_TRAPDOOR = register(new BlockItem(builder(), Blocks.JUNGLE_TRAPDOOR)); + public static final Item ACACIA_TRAPDOOR = register(new BlockItem(builder(), Blocks.ACACIA_TRAPDOOR)); + public static final Item CHERRY_TRAPDOOR = register(new BlockItem(builder(), Blocks.CHERRY_TRAPDOOR)); + public static final Item DARK_OAK_TRAPDOOR = register(new BlockItem(builder(), Blocks.DARK_OAK_TRAPDOOR)); + public static final Item MANGROVE_TRAPDOOR = register(new BlockItem(builder(), Blocks.MANGROVE_TRAPDOOR)); + public static final Item BAMBOO_TRAPDOOR = register(new BlockItem(builder(), Blocks.BAMBOO_TRAPDOOR)); + public static final Item CRIMSON_TRAPDOOR = register(new BlockItem(builder(), Blocks.CRIMSON_TRAPDOOR)); + public static final Item WARPED_TRAPDOOR = register(new BlockItem(builder(), Blocks.WARPED_TRAPDOOR)); + public static final Item COPPER_TRAPDOOR = register(new BlockItem(builder(), Blocks.COPPER_TRAPDOOR)); + public static final Item EXPOSED_COPPER_TRAPDOOR = register(new BlockItem(builder(), Blocks.EXPOSED_COPPER_TRAPDOOR)); + public static final Item WEATHERED_COPPER_TRAPDOOR = register(new BlockItem(builder(), Blocks.WEATHERED_COPPER_TRAPDOOR)); + public static final Item OXIDIZED_COPPER_TRAPDOOR = register(new BlockItem(builder(), Blocks.OXIDIZED_COPPER_TRAPDOOR)); + public static final Item WAXED_COPPER_TRAPDOOR = register(new BlockItem(builder(), Blocks.WAXED_COPPER_TRAPDOOR)); + public static final Item WAXED_EXPOSED_COPPER_TRAPDOOR = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_COPPER_TRAPDOOR)); + public static final Item WAXED_WEATHERED_COPPER_TRAPDOOR = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_COPPER_TRAPDOOR)); + public static final Item WAXED_OXIDIZED_COPPER_TRAPDOOR = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_COPPER_TRAPDOOR)); + public static final Item OAK_FENCE_GATE = register(new BlockItem(builder(), Blocks.OAK_FENCE_GATE)); + public static final Item SPRUCE_FENCE_GATE = register(new BlockItem(builder(), Blocks.SPRUCE_FENCE_GATE)); + public static final Item BIRCH_FENCE_GATE = register(new BlockItem(builder(), Blocks.BIRCH_FENCE_GATE)); + public static final Item JUNGLE_FENCE_GATE = register(new BlockItem(builder(), Blocks.JUNGLE_FENCE_GATE)); + public static final Item ACACIA_FENCE_GATE = register(new BlockItem(builder(), Blocks.ACACIA_FENCE_GATE)); + public static final Item CHERRY_FENCE_GATE = register(new BlockItem(builder(), Blocks.CHERRY_FENCE_GATE)); + public static final Item DARK_OAK_FENCE_GATE = register(new BlockItem(builder(), Blocks.DARK_OAK_FENCE_GATE)); + public static final Item MANGROVE_FENCE_GATE = register(new BlockItem(builder(), Blocks.MANGROVE_FENCE_GATE)); + public static final Item BAMBOO_FENCE_GATE = register(new BlockItem(builder(), Blocks.BAMBOO_FENCE_GATE)); + public static final Item CRIMSON_FENCE_GATE = register(new BlockItem(builder(), Blocks.CRIMSON_FENCE_GATE)); + public static final Item WARPED_FENCE_GATE = register(new BlockItem(builder(), Blocks.WARPED_FENCE_GATE)); + public static final Item POWERED_RAIL = register(new BlockItem(builder(), Blocks.POWERED_RAIL)); + public static final Item DETECTOR_RAIL = register(new BlockItem(builder(), Blocks.DETECTOR_RAIL)); + public static final Item RAIL = register(new BlockItem(builder(), Blocks.RAIL)); + public static final Item ACTIVATOR_RAIL = register(new BlockItem(builder(), Blocks.ACTIVATOR_RAIL)); public static final Item SADDLE = register(new Item("saddle", builder().stackSize(1))); public static final Item MINECART = register(new Item("minecart", builder().stackSize(1))); public static final Item CHEST_MINECART = register(new Item("chest_minecart", builder().stackSize(1))); @@ -830,8 +831,8 @@ public final class Items { public static final Item MANGROVE_CHEST_BOAT = register(new BoatItem("mangrove_chest_boat", builder().stackSize(1))); public static final Item BAMBOO_RAFT = register(new BoatItem("bamboo_raft", builder().stackSize(1))); public static final Item BAMBOO_CHEST_RAFT = register(new BoatItem("bamboo_chest_raft", builder().stackSize(1))); - 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 STRUCTURE_BLOCK = register(new BlockItem(builder(), Blocks.STRUCTURE_BLOCK)); + public static final Item JIGSAW = register(new BlockItem(builder(), Blocks.JIGSAW)); public static final Item TURTLE_HELMET = register(new ArmorItem("turtle_helmet", ArmorMaterial.TURTLE, builder().stackSize(1).maxDamage(275))); public static final Item TURTLE_SCUTE = register(new Item("turtle_scute", builder())); public static final Item ARMADILLO_SCUTE = register(new Item("armadillo_scute", builder())); @@ -888,10 +889,10 @@ public final class Items { 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))); - public static final Item STRING = register(new BlockItem("string", builder())); + public static final Item STRING = register(new BlockItem("string", builder(), Blocks.TRIPWIRE)); public static final Item FEATHER = register(new Item("feather", builder())); public static final Item GUNPOWDER = register(new Item("gunpowder", builder())); - public static final Item WHEAT_SEEDS = register(new BlockItem("wheat_seeds", builder())); + public static final Item WHEAT_SEEDS = register(new BlockItem("wheat_seeds", builder(), Blocks.WHEAT)); 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))); @@ -924,32 +925,32 @@ public final class Items { public static final Item PAINTING = register(new Item("painting", builder())); public static final Item GOLDEN_APPLE = register(new Item("golden_apple", builder())); public static final Item ENCHANTED_GOLDEN_APPLE = register(new Item("enchanted_golden_apple", builder())); - public static final Item OAK_SIGN = register(new BlockItem("oak_sign", builder().stackSize(16))); - public static final Item SPRUCE_SIGN = register(new BlockItem("spruce_sign", builder().stackSize(16))); - public static final Item BIRCH_SIGN = register(new BlockItem("birch_sign", builder().stackSize(16))); - public static final Item JUNGLE_SIGN = register(new BlockItem("jungle_sign", builder().stackSize(16))); - public static final Item ACACIA_SIGN = register(new BlockItem("acacia_sign", builder().stackSize(16))); - public static final Item CHERRY_SIGN = register(new BlockItem("cherry_sign", builder().stackSize(16))); - public static final Item DARK_OAK_SIGN = register(new BlockItem("dark_oak_sign", builder().stackSize(16))); - public static final Item MANGROVE_SIGN = register(new BlockItem("mangrove_sign", builder().stackSize(16))); - public static final Item BAMBOO_SIGN = register(new BlockItem("bamboo_sign", builder().stackSize(16))); - public static final Item CRIMSON_SIGN = register(new BlockItem("crimson_sign", builder().stackSize(16))); - public static final Item WARPED_SIGN = register(new BlockItem("warped_sign", builder().stackSize(16))); - public static final Item OAK_HANGING_SIGN = register(new BlockItem("oak_hanging_sign", builder().stackSize(16))); - public static final Item SPRUCE_HANGING_SIGN = register(new BlockItem("spruce_hanging_sign", builder().stackSize(16))); - public static final Item BIRCH_HANGING_SIGN = register(new BlockItem("birch_hanging_sign", builder().stackSize(16))); - public static final Item JUNGLE_HANGING_SIGN = register(new BlockItem("jungle_hanging_sign", builder().stackSize(16))); - public static final Item ACACIA_HANGING_SIGN = register(new BlockItem("acacia_hanging_sign", builder().stackSize(16))); - public static final Item CHERRY_HANGING_SIGN = register(new BlockItem("cherry_hanging_sign", builder().stackSize(16))); - public static final Item DARK_OAK_HANGING_SIGN = register(new BlockItem("dark_oak_hanging_sign", builder().stackSize(16))); - public static final Item MANGROVE_HANGING_SIGN = register(new BlockItem("mangrove_hanging_sign", builder().stackSize(16))); - public static final Item BAMBOO_HANGING_SIGN = register(new BlockItem("bamboo_hanging_sign", builder().stackSize(16))); - public static final Item CRIMSON_HANGING_SIGN = register(new BlockItem("crimson_hanging_sign", builder().stackSize(16))); - public static final Item WARPED_HANGING_SIGN = register(new BlockItem("warped_hanging_sign", builder().stackSize(16))); + public static final Item OAK_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.OAK_SIGN, Blocks.OAK_WALL_SIGN)); + public static final Item SPRUCE_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.SPRUCE_SIGN, Blocks.SPRUCE_WALL_SIGN)); + public static final Item BIRCH_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.BIRCH_SIGN, Blocks.BIRCH_WALL_SIGN)); + public static final Item JUNGLE_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.JUNGLE_SIGN, Blocks.JUNGLE_WALL_SIGN)); + public static final Item ACACIA_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.ACACIA_SIGN, Blocks.ACACIA_WALL_SIGN)); + public static final Item CHERRY_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.CHERRY_SIGN, Blocks.CHERRY_WALL_SIGN)); + public static final Item DARK_OAK_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.DARK_OAK_SIGN, Blocks.DARK_OAK_WALL_SIGN)); + public static final Item MANGROVE_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.MANGROVE_SIGN, Blocks.MANGROVE_WALL_SIGN)); + public static final Item BAMBOO_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.BAMBOO_SIGN, Blocks.BAMBOO_WALL_SIGN)); + public static final Item CRIMSON_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.CRIMSON_SIGN, Blocks.CRIMSON_WALL_SIGN)); + public static final Item WARPED_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.WARPED_SIGN, Blocks.WARPED_WALL_SIGN)); + public static final Item OAK_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.OAK_HANGING_SIGN, Blocks.OAK_WALL_HANGING_SIGN)); + public static final Item SPRUCE_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.SPRUCE_HANGING_SIGN, Blocks.SPRUCE_WALL_HANGING_SIGN)); + public static final Item BIRCH_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.BIRCH_HANGING_SIGN, Blocks.BIRCH_WALL_HANGING_SIGN)); + public static final Item JUNGLE_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.JUNGLE_HANGING_SIGN, Blocks.JUNGLE_WALL_HANGING_SIGN)); + public static final Item ACACIA_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.ACACIA_HANGING_SIGN, Blocks.ACACIA_WALL_HANGING_SIGN)); + public static final Item CHERRY_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.CHERRY_HANGING_SIGN, Blocks.CHERRY_WALL_HANGING_SIGN)); + public static final Item DARK_OAK_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.DARK_OAK_HANGING_SIGN, Blocks.DARK_OAK_WALL_HANGING_SIGN)); + public static final Item MANGROVE_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.MANGROVE_HANGING_SIGN, Blocks.MANGROVE_WALL_HANGING_SIGN)); + public static final Item BAMBOO_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.BAMBOO_HANGING_SIGN, Blocks.BAMBOO_WALL_HANGING_SIGN)); + public static final Item CRIMSON_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.CRIMSON_HANGING_SIGN, Blocks.CRIMSON_WALL_HANGING_SIGN)); + public static final Item WARPED_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.WARPED_HANGING_SIGN, Blocks.WARPED_WALL_HANGING_SIGN)); public static final Item BUCKET = register(new Item("bucket", builder().stackSize(16))); public static final Item WATER_BUCKET = register(new Item("water_bucket", builder().stackSize(1))); public static final Item LAVA_BUCKET = register(new Item("lava_bucket", builder().stackSize(1))); - public static final Item POWDER_SNOW_BUCKET = register(new BlockItem("powder_snow_bucket", builder().stackSize(1))); + public static final Item POWDER_SNOW_BUCKET = register(new BlockItem("powder_snow_bucket", builder().stackSize(1), Blocks.POWDER_SNOW)); public static final Item SNOWBALL = register(new Item("snowball", builder().stackSize(16))); public static final Item LEATHER = register(new Item("leather", builder())); public static final Item MILK_BUCKET = register(new Item("milk_bucket", builder().stackSize(1))); @@ -961,7 +962,7 @@ public final class Items { public static final Item TADPOLE_BUCKET = register(new Item("tadpole_bucket", builder().stackSize(1))); public static final Item BRICK = register(new Item("brick", builder())); public static final Item CLAY_BALL = register(new Item("clay_ball", builder())); - public static final Item DRIED_KELP_BLOCK = register(new BlockItem("dried_kelp_block", builder())); + public static final Item DRIED_KELP_BLOCK = register(new BlockItem(builder(), Blocks.DRIED_KELP_BLOCK)); public static final Item PAPER = register(new Item("paper", builder())); public static final Item BOOK = register(new Item("book", builder())); public static final Item SLIME_BALL = register(new Item("slime_ball", builder())); @@ -981,7 +982,7 @@ public final class Items { public static final Item COOKED_SALMON = register(new Item("cooked_salmon", builder())); public static final Item INK_SAC = register(new Item("ink_sac", builder())); public static final Item GLOW_INK_SAC = register(new Item("glow_ink_sac", builder())); - public static final Item COCOA_BEANS = register(new BlockItem("cocoa_beans", builder())); + public static final Item COCOA_BEANS = register(new BlockItem("cocoa_beans", builder(), Blocks.COCOA)); public static final Item WHITE_DYE = register(new DyeItem("white_dye", 0, builder())); public static final Item ORANGE_DYE = register(new DyeItem("orange_dye", 1, builder())); public static final Item MAGENTA_DYE = register(new DyeItem("magenta_dye", 2, builder())); @@ -1001,31 +1002,31 @@ public final class Items { public static final Item BONE_MEAL = register(new Item("bone_meal", builder())); public static final Item BONE = register(new Item("bone", builder())); public static final Item SUGAR = register(new Item("sugar", builder())); - public static final Item CAKE = register(new BlockItem("cake", builder().stackSize(1))); - public static final Item WHITE_BED = register(new BlockItem("white_bed", builder().stackSize(1))); - public static final Item ORANGE_BED = register(new BlockItem("orange_bed", builder().stackSize(1))); - public static final Item MAGENTA_BED = register(new BlockItem("magenta_bed", builder().stackSize(1))); - public static final Item LIGHT_BLUE_BED = register(new BlockItem("light_blue_bed", builder().stackSize(1))); - public static final Item YELLOW_BED = register(new BlockItem("yellow_bed", builder().stackSize(1))); - public static final Item LIME_BED = register(new BlockItem("lime_bed", builder().stackSize(1))); - public static final Item PINK_BED = register(new BlockItem("pink_bed", builder().stackSize(1))); - public static final Item GRAY_BED = register(new BlockItem("gray_bed", builder().stackSize(1))); - public static final Item LIGHT_GRAY_BED = register(new BlockItem("light_gray_bed", builder().stackSize(1))); - public static final Item CYAN_BED = register(new BlockItem("cyan_bed", builder().stackSize(1))); - public static final Item PURPLE_BED = register(new BlockItem("purple_bed", builder().stackSize(1))); - public static final Item BLUE_BED = register(new BlockItem("blue_bed", builder().stackSize(1))); - public static final Item BROWN_BED = register(new BlockItem("brown_bed", builder().stackSize(1))); - public static final Item GREEN_BED = register(new BlockItem("green_bed", builder().stackSize(1))); - 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 CAKE = register(new BlockItem(builder().stackSize(1), Blocks.CAKE)); + public static final Item WHITE_BED = register(new BlockItem(builder().stackSize(1), Blocks.WHITE_BED)); + public static final Item ORANGE_BED = register(new BlockItem(builder().stackSize(1), Blocks.ORANGE_BED)); + public static final Item MAGENTA_BED = register(new BlockItem(builder().stackSize(1), Blocks.MAGENTA_BED)); + public static final Item LIGHT_BLUE_BED = register(new BlockItem(builder().stackSize(1), Blocks.LIGHT_BLUE_BED)); + public static final Item YELLOW_BED = register(new BlockItem(builder().stackSize(1), Blocks.YELLOW_BED)); + public static final Item LIME_BED = register(new BlockItem(builder().stackSize(1), Blocks.LIME_BED)); + public static final Item PINK_BED = register(new BlockItem(builder().stackSize(1), Blocks.PINK_BED)); + public static final Item GRAY_BED = register(new BlockItem(builder().stackSize(1), Blocks.GRAY_BED)); + public static final Item LIGHT_GRAY_BED = register(new BlockItem(builder().stackSize(1), Blocks.LIGHT_GRAY_BED)); + public static final Item CYAN_BED = register(new BlockItem(builder().stackSize(1), Blocks.CYAN_BED)); + public static final Item PURPLE_BED = register(new BlockItem(builder().stackSize(1), Blocks.PURPLE_BED)); + public static final Item BLUE_BED = register(new BlockItem(builder().stackSize(1), Blocks.BLUE_BED)); + public static final Item BROWN_BED = register(new BlockItem(builder().stackSize(1), Blocks.BROWN_BED)); + public static final Item GREEN_BED = register(new BlockItem(builder().stackSize(1), Blocks.GREEN_BED)); + public static final Item RED_BED = register(new BlockItem(builder().stackSize(1), Blocks.RED_BED)); + public static final Item BLACK_BED = register(new BlockItem(builder().stackSize(1), Blocks.BLACK_BED)); public static final Item COOKIE = register(new Item("cookie", builder())); - public static final Item CRAFTER = register(new BlockItem("crafter", builder())); + public static final Item CRAFTER = register(new BlockItem(builder(), Blocks.CRAFTER)); 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())); public static final Item DRIED_KELP = register(new Item("dried_kelp", builder())); - public static final Item PUMPKIN_SEEDS = register(new BlockItem("pumpkin_seeds", builder())); - public static final Item MELON_SEEDS = register(new BlockItem("melon_seeds", builder())); + public static final Item PUMPKIN_SEEDS = register(new BlockItem("pumpkin_seeds", builder(), Blocks.PUMPKIN_STEM)); + public static final Item MELON_SEEDS = register(new BlockItem("melon_seeds", builder(), Blocks.MELON_STEM)); public static final Item BEEF = register(new Item("beef", builder())); public static final Item COOKED_BEEF = register(new Item("cooked_beef", builder())); public static final Item CHICKEN = register(new Item("chicken", builder())); @@ -1035,15 +1036,15 @@ public final class Items { public static final Item BLAZE_ROD = register(new Item("blaze_rod", builder())); public static final Item GHAST_TEAR = register(new Item("ghast_tear", builder())); public static final Item GOLD_NUGGET = register(new Item("gold_nugget", builder())); - public static final Item NETHER_WART = register(new BlockItem("nether_wart", builder())); + public static final Item NETHER_WART = register(new BlockItem(builder(), Blocks.NETHER_WART)); public static final Item POTION = register(new PotionItem("potion", builder().stackSize(1))); public static final Item GLASS_BOTTLE = register(new Item("glass_bottle", builder())); public static final Item SPIDER_EYE = register(new Item("spider_eye", builder())); public static final Item FERMENTED_SPIDER_EYE = register(new Item("fermented_spider_eye", builder())); public static final Item BLAZE_POWDER = register(new Item("blaze_powder", builder())); public static final Item MAGMA_CREAM = register(new Item("magma_cream", builder())); - public static final Item BREWING_STAND = register(new BlockItem("brewing_stand", builder())); - public static final Item CAULDRON = register(new BlockItem("cauldron", builder())); + public static final Item BREWING_STAND = register(new BlockItem(builder(), Blocks.BREWING_STAND)); + public static final Item CAULDRON = register(new BlockItem(builder(), Blocks.CAULDRON, Blocks.LAVA_CAULDRON, Blocks.POWDER_SNOW_CAULDRON, Blocks.WATER_CAULDRON)); 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())); @@ -1134,20 +1135,20 @@ public final class Items { 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())); - public static final Item CARROT = register(new BlockItem("carrot", builder())); - public static final Item POTATO = register(new BlockItem("potato", builder())); + public static final Item FLOWER_POT = register(new BlockItem(builder(), Blocks.FLOWER_POT)); + public static final Item CARROT = register(new BlockItem("carrot", builder(), Blocks.CARROTS)); + public static final Item POTATO = register(new BlockItem("potato", builder(), Blocks.POTATOES)); public static final Item BAKED_POTATO = register(new Item("baked_potato", builder())); public static final Item POISONOUS_POTATO = register(new Item("poisonous_potato", builder())); public static final Item MAP = register(new MapItem("map", builder())); public static final Item GOLDEN_CARROT = register(new Item("golden_carrot", builder())); - public static final Item SKELETON_SKULL = register(new BlockItem("skeleton_skull", builder())); - public static final Item WITHER_SKELETON_SKULL = register(new BlockItem("wither_skeleton_skull", builder())); - public static final Item PLAYER_HEAD = register(new PlayerHeadItem("player_head", builder())); - public static final Item ZOMBIE_HEAD = register(new BlockItem("zombie_head", builder())); - public static final Item CREEPER_HEAD = register(new BlockItem("creeper_head", builder())); - public static final Item DRAGON_HEAD = register(new BlockItem("dragon_head", builder())); - public static final Item PIGLIN_HEAD = register(new BlockItem("piglin_head", builder())); + public static final Item SKELETON_SKULL = register(new BlockItem(builder(), Blocks.SKELETON_SKULL, Blocks.SKELETON_WALL_SKULL)); + public static final Item WITHER_SKELETON_SKULL = register(new BlockItem(builder(), Blocks.WITHER_SKELETON_SKULL, Blocks.WITHER_SKELETON_WALL_SKULL)); + public static final Item PLAYER_HEAD = register(new PlayerHeadItem(builder(), Blocks.PLAYER_HEAD, Blocks.PLAYER_WALL_HEAD)); + public static final Item ZOMBIE_HEAD = register(new BlockItem(builder(), Blocks.ZOMBIE_HEAD, Blocks.ZOMBIE_WALL_HEAD)); + public static final Item CREEPER_HEAD = register(new BlockItem(builder(), Blocks.CREEPER_HEAD, Blocks.CREEPER_WALL_HEAD)); + public static final Item DRAGON_HEAD = register(new BlockItem(builder(), Blocks.DRAGON_HEAD, Blocks.DRAGON_WALL_HEAD)); + public static final Item PIGLIN_HEAD = register(new BlockItem(builder(), Blocks.PIGLIN_HEAD, Blocks.PIGLIN_WALL_HEAD)); public static final Item NETHER_STAR = register(new Item("nether_star", builder())); public static final Item PUMPKIN_PIE = register(new Item("pumpkin_pie", builder())); public static final Item FIREWORK_ROCKET = register(new FireworkRocketItem("firework_rocket", builder())); @@ -1171,29 +1172,29 @@ public final class Items { public static final Item COMMAND_BLOCK_MINECART = register(new Item("command_block_minecart", builder().stackSize(1))); public static final Item MUTTON = register(new Item("mutton", builder())); public static final Item COOKED_MUTTON = register(new Item("cooked_mutton", builder())); - public static final Item WHITE_BANNER = register(new BannerItem("white_banner", builder().stackSize(16))); - public static final Item ORANGE_BANNER = register(new BannerItem("orange_banner", builder().stackSize(16))); - public static final Item MAGENTA_BANNER = register(new BannerItem("magenta_banner", builder().stackSize(16))); - public static final Item LIGHT_BLUE_BANNER = register(new BannerItem("light_blue_banner", builder().stackSize(16))); - public static final Item YELLOW_BANNER = register(new BannerItem("yellow_banner", builder().stackSize(16))); - public static final Item LIME_BANNER = register(new BannerItem("lime_banner", builder().stackSize(16))); - public static final Item PINK_BANNER = register(new BannerItem("pink_banner", builder().stackSize(16))); - public static final Item GRAY_BANNER = register(new BannerItem("gray_banner", builder().stackSize(16))); - public static final Item LIGHT_GRAY_BANNER = register(new BannerItem("light_gray_banner", builder().stackSize(16))); - public static final Item CYAN_BANNER = register(new BannerItem("cyan_banner", builder().stackSize(16))); - public static final Item PURPLE_BANNER = register(new BannerItem("purple_banner", builder().stackSize(16))); - public static final Item BLUE_BANNER = register(new BannerItem("blue_banner", builder().stackSize(16))); - public static final Item BROWN_BANNER = register(new BannerItem("brown_banner", builder().stackSize(16))); - public static final Item GREEN_BANNER = register(new BannerItem("green_banner", builder().stackSize(16))); - public static final Item RED_BANNER = register(new BannerItem("red_banner", builder().stackSize(16))); - public static final Item BLACK_BANNER = register(new BannerItem("black_banner", builder().stackSize(16))); + public static final Item WHITE_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.WHITE_BANNER, Blocks.WHITE_WALL_BANNER)); + public static final Item ORANGE_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.ORANGE_BANNER, Blocks.ORANGE_WALL_BANNER)); + public static final Item MAGENTA_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.MAGENTA_BANNER, Blocks.MAGENTA_WALL_BANNER)); + public static final Item LIGHT_BLUE_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.LIGHT_BLUE_BANNER, Blocks.LIGHT_BLUE_WALL_BANNER)); + public static final Item YELLOW_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.YELLOW_BANNER, Blocks.YELLOW_WALL_BANNER)); + public static final Item LIME_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.LIME_BANNER, Blocks.LIME_WALL_BANNER)); + public static final Item PINK_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.PINK_BANNER, Blocks.PINK_WALL_BANNER)); + public static final Item GRAY_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.GRAY_BANNER, Blocks.GRAY_WALL_BANNER)); + public static final Item LIGHT_GRAY_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.LIGHT_GRAY_BANNER, Blocks.LIGHT_GRAY_WALL_BANNER)); + public static final Item CYAN_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.CYAN_BANNER, Blocks.CYAN_WALL_BANNER)); + public static final Item PURPLE_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.PURPLE_BANNER, Blocks.PURPLE_WALL_BANNER)); + public static final Item BLUE_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.BLUE_BANNER, Blocks.BLUE_WALL_BANNER)); + public static final Item BROWN_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.BROWN_BANNER, Blocks.BROWN_WALL_BANNER)); + public static final Item GREEN_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.GREEN_BANNER, Blocks.GREEN_WALL_BANNER)); + public static final Item RED_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.RED_BANNER, Blocks.RED_WALL_BANNER)); + public static final Item BLACK_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.BLACK_BANNER, Blocks.BLACK_WALL_BANNER)); public static final Item END_CRYSTAL = register(new Item("end_crystal", builder())); public static final Item CHORUS_FRUIT = register(new Item("chorus_fruit", builder())); public static final Item POPPED_CHORUS_FRUIT = register(new Item("popped_chorus_fruit", builder())); - public static final Item TORCHFLOWER_SEEDS = register(new BlockItem("torchflower_seeds", builder())); - public static final Item PITCHER_POD = register(new BlockItem("pitcher_pod", builder())); + public static final Item TORCHFLOWER_SEEDS = register(new BlockItem("torchflower_seeds", builder(), Blocks.TORCHFLOWER_CROP)); + public static final Item PITCHER_POD = register(new BlockItem("pitcher_pod", builder(), Blocks.PITCHER_CROP)); public static final Item BEETROOT = register(new Item("beetroot", builder())); - public static final Item BEETROOT_SEEDS = register(new BlockItem("beetroot_seeds", builder())); + public static final Item BEETROOT_SEEDS = register(new BlockItem("beetroot_seeds", builder(), Blocks.BEETROOTS)); public static final Item BEETROOT_SOUP = register(new Item("beetroot_soup", builder().stackSize(1))); public static final Item DRAGON_BREATH = register(new Item("dragon_breath", builder())); public static final Item SPLASH_POTION = register(new PotionItem("splash_potion", builder().stackSize(1))); @@ -1229,7 +1230,7 @@ public final class Items { public static final Item HEART_OF_THE_SEA = register(new Item("heart_of_the_sea", builder())); public static final Item CROSSBOW = register(new CrossbowItem("crossbow", builder().stackSize(1).maxDamage(465))); public static final Item SUSPICIOUS_STEW = register(new Item("suspicious_stew", builder().stackSize(1))); - public static final Item LOOM = register(new BlockItem("loom", builder())); + public static final Item LOOM = register(new BlockItem(builder(), Blocks.LOOM)); public static final Item FLOWER_BANNER_PATTERN = register(new Item("flower_banner_pattern", builder().stackSize(1))); public static final Item CREEPER_BANNER_PATTERN = register(new Item("creeper_banner_pattern", builder().stackSize(1))); public static final Item SKULL_BANNER_PATTERN = register(new Item("skull_banner_pattern", builder().stackSize(1))); @@ -1239,69 +1240,69 @@ public final class Items { 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 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())); - public static final Item FLETCHING_TABLE = register(new BlockItem("fletching_table", builder())); - public static final Item GRINDSTONE = register(new BlockItem("grindstone", builder())); - public static final Item SMITHING_TABLE = register(new BlockItem("smithing_table", builder())); - public static final Item STONECUTTER = register(new BlockItem("stonecutter", builder())); - public static final Item BELL = register(new BlockItem("bell", builder())); - public static final Item LANTERN = register(new BlockItem("lantern", builder())); - public static final Item SOUL_LANTERN = register(new BlockItem("soul_lantern", builder())); - public static final Item SWEET_BERRIES = register(new BlockItem("sweet_berries", builder())); - public static final Item GLOW_BERRIES = register(new BlockItem("glow_berries", builder())); - public static final Item CAMPFIRE = register(new BlockItem("campfire", builder())); - public static final Item SOUL_CAMPFIRE = register(new BlockItem("soul_campfire", builder())); - public static final Item SHROOMLIGHT = register(new BlockItem("shroomlight", builder())); + public static final Item COMPOSTER = register(new BlockItem(builder(), Blocks.COMPOSTER)); + public static final Item BARREL = register(new BlockItem(builder(), Blocks.BARREL)); + public static final Item SMOKER = register(new BlockItem(builder(), Blocks.SMOKER)); + public static final Item BLAST_FURNACE = register(new BlockItem(builder(), Blocks.BLAST_FURNACE)); + public static final Item CARTOGRAPHY_TABLE = register(new BlockItem(builder(), Blocks.CARTOGRAPHY_TABLE)); + public static final Item FLETCHING_TABLE = register(new BlockItem(builder(), Blocks.FLETCHING_TABLE)); + public static final Item GRINDSTONE = register(new BlockItem(builder(), Blocks.GRINDSTONE)); + public static final Item SMITHING_TABLE = register(new BlockItem(builder(), Blocks.SMITHING_TABLE)); + public static final Item STONECUTTER = register(new BlockItem(builder(), Blocks.STONECUTTER)); + public static final Item BELL = register(new BlockItem(builder(), Blocks.BELL)); + public static final Item LANTERN = register(new BlockItem(builder(), Blocks.LANTERN)); + public static final Item SOUL_LANTERN = register(new BlockItem(builder(), Blocks.SOUL_LANTERN)); + public static final Item SWEET_BERRIES = register(new BlockItem("sweet_berries", builder(), Blocks.SWEET_BERRY_BUSH)); + public static final Item GLOW_BERRIES = register(new BlockItem("glow_berries", builder(), Blocks.CAVE_VINES)); + public static final Item CAMPFIRE = register(new BlockItem(builder(), Blocks.CAMPFIRE)); + public static final Item SOUL_CAMPFIRE = register(new BlockItem(builder(), Blocks.SOUL_CAMPFIRE)); + public static final Item SHROOMLIGHT = register(new BlockItem(builder(), Blocks.SHROOMLIGHT)); public static final Item HONEYCOMB = register(new Item("honeycomb", builder())); - public static final Item BEE_NEST = register(new BlockItem("bee_nest", builder())); - public static final Item BEEHIVE = register(new BlockItem("beehive", builder())); + public static final Item BEE_NEST = register(new BlockItem(builder(), Blocks.BEE_NEST)); + public static final Item BEEHIVE = register(new BlockItem(builder(), Blocks.BEEHIVE)); public static final Item HONEY_BOTTLE = register(new Item("honey_bottle", builder().stackSize(16))); - public static final Item HONEYCOMB_BLOCK = register(new BlockItem("honeycomb_block", builder())); - public static final Item LODESTONE = register(new BlockItem("lodestone", builder())); - public static final Item CRYING_OBSIDIAN = register(new BlockItem("crying_obsidian", builder())); - public static final Item BLACKSTONE = register(new BlockItem("blackstone", builder())); - public static final Item BLACKSTONE_SLAB = register(new BlockItem("blackstone_slab", builder())); - public static final Item BLACKSTONE_STAIRS = register(new BlockItem("blackstone_stairs", builder())); - public static final Item GILDED_BLACKSTONE = register(new BlockItem("gilded_blackstone", builder())); - public static final Item POLISHED_BLACKSTONE = register(new BlockItem("polished_blackstone", builder())); - public static final Item POLISHED_BLACKSTONE_SLAB = register(new BlockItem("polished_blackstone_slab", builder())); - public static final Item POLISHED_BLACKSTONE_STAIRS = register(new BlockItem("polished_blackstone_stairs", builder())); - public static final Item CHISELED_POLISHED_BLACKSTONE = register(new BlockItem("chiseled_polished_blackstone", builder())); - public static final Item POLISHED_BLACKSTONE_BRICKS = register(new BlockItem("polished_blackstone_bricks", builder())); - public static final Item POLISHED_BLACKSTONE_BRICK_SLAB = register(new BlockItem("polished_blackstone_brick_slab", builder())); - public static final Item POLISHED_BLACKSTONE_BRICK_STAIRS = register(new BlockItem("polished_blackstone_brick_stairs", builder())); - public static final Item CRACKED_POLISHED_BLACKSTONE_BRICKS = register(new BlockItem("cracked_polished_blackstone_bricks", builder())); - public static final Item RESPAWN_ANCHOR = register(new BlockItem("respawn_anchor", builder())); - public static final Item CANDLE = register(new BlockItem("candle", builder())); - public static final Item WHITE_CANDLE = register(new BlockItem("white_candle", builder())); - public static final Item ORANGE_CANDLE = register(new BlockItem("orange_candle", builder())); - public static final Item MAGENTA_CANDLE = register(new BlockItem("magenta_candle", builder())); - public static final Item LIGHT_BLUE_CANDLE = register(new BlockItem("light_blue_candle", builder())); - public static final Item YELLOW_CANDLE = register(new BlockItem("yellow_candle", builder())); - public static final Item LIME_CANDLE = register(new BlockItem("lime_candle", builder())); - public static final Item PINK_CANDLE = register(new BlockItem("pink_candle", builder())); - public static final Item GRAY_CANDLE = register(new BlockItem("gray_candle", builder())); - public static final Item LIGHT_GRAY_CANDLE = register(new BlockItem("light_gray_candle", builder())); - public static final Item CYAN_CANDLE = register(new BlockItem("cyan_candle", builder())); - public static final Item PURPLE_CANDLE = register(new BlockItem("purple_candle", builder())); - public static final Item BLUE_CANDLE = register(new BlockItem("blue_candle", builder())); - public static final Item BROWN_CANDLE = register(new BlockItem("brown_candle", builder())); - public static final Item GREEN_CANDLE = register(new BlockItem("green_candle", builder())); - public static final Item RED_CANDLE = register(new BlockItem("red_candle", builder())); - public static final Item BLACK_CANDLE = register(new BlockItem("black_candle", builder())); - public static final Item SMALL_AMETHYST_BUD = register(new BlockItem("small_amethyst_bud", builder())); - public static final Item MEDIUM_AMETHYST_BUD = register(new BlockItem("medium_amethyst_bud", builder())); - public static final Item LARGE_AMETHYST_BUD = register(new BlockItem("large_amethyst_bud", builder())); - public static final Item AMETHYST_CLUSTER = register(new BlockItem("amethyst_cluster", builder())); - public static final Item POINTED_DRIPSTONE = register(new BlockItem("pointed_dripstone", builder())); - public static final Item OCHRE_FROGLIGHT = register(new BlockItem("ochre_froglight", builder())); - public static final Item VERDANT_FROGLIGHT = register(new BlockItem("verdant_froglight", builder())); - public static final Item PEARLESCENT_FROGLIGHT = register(new BlockItem("pearlescent_froglight", builder())); - public static final Item FROGSPAWN = register(new BlockItem("frogspawn", builder())); + public static final Item HONEYCOMB_BLOCK = register(new BlockItem(builder(), Blocks.HONEYCOMB_BLOCK)); + public static final Item LODESTONE = register(new BlockItem(builder(), Blocks.LODESTONE)); + public static final Item CRYING_OBSIDIAN = register(new BlockItem(builder(), Blocks.CRYING_OBSIDIAN)); + public static final Item BLACKSTONE = register(new BlockItem(builder(), Blocks.BLACKSTONE)); + public static final Item BLACKSTONE_SLAB = register(new BlockItem(builder(), Blocks.BLACKSTONE_SLAB)); + public static final Item BLACKSTONE_STAIRS = register(new BlockItem(builder(), Blocks.BLACKSTONE_STAIRS)); + public static final Item GILDED_BLACKSTONE = register(new BlockItem(builder(), Blocks.GILDED_BLACKSTONE)); + public static final Item POLISHED_BLACKSTONE = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE)); + public static final Item POLISHED_BLACKSTONE_SLAB = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_SLAB)); + public static final Item POLISHED_BLACKSTONE_STAIRS = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_STAIRS)); + public static final Item CHISELED_POLISHED_BLACKSTONE = register(new BlockItem(builder(), Blocks.CHISELED_POLISHED_BLACKSTONE)); + public static final Item POLISHED_BLACKSTONE_BRICKS = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_BRICKS)); + public static final Item POLISHED_BLACKSTONE_BRICK_SLAB = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_BRICK_SLAB)); + public static final Item POLISHED_BLACKSTONE_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.POLISHED_BLACKSTONE_BRICK_STAIRS)); + public static final Item CRACKED_POLISHED_BLACKSTONE_BRICKS = register(new BlockItem(builder(), Blocks.CRACKED_POLISHED_BLACKSTONE_BRICKS)); + public static final Item RESPAWN_ANCHOR = register(new BlockItem(builder(), Blocks.RESPAWN_ANCHOR)); + public static final Item CANDLE = register(new BlockItem(builder(), Blocks.CANDLE)); + public static final Item WHITE_CANDLE = register(new BlockItem(builder(), Blocks.WHITE_CANDLE)); + public static final Item ORANGE_CANDLE = register(new BlockItem(builder(), Blocks.ORANGE_CANDLE)); + public static final Item MAGENTA_CANDLE = register(new BlockItem(builder(), Blocks.MAGENTA_CANDLE)); + public static final Item LIGHT_BLUE_CANDLE = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_CANDLE)); + public static final Item YELLOW_CANDLE = register(new BlockItem(builder(), Blocks.YELLOW_CANDLE)); + public static final Item LIME_CANDLE = register(new BlockItem(builder(), Blocks.LIME_CANDLE)); + public static final Item PINK_CANDLE = register(new BlockItem(builder(), Blocks.PINK_CANDLE)); + public static final Item GRAY_CANDLE = register(new BlockItem(builder(), Blocks.GRAY_CANDLE)); + public static final Item LIGHT_GRAY_CANDLE = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_CANDLE)); + public static final Item CYAN_CANDLE = register(new BlockItem(builder(), Blocks.CYAN_CANDLE)); + public static final Item PURPLE_CANDLE = register(new BlockItem(builder(), Blocks.PURPLE_CANDLE)); + public static final Item BLUE_CANDLE = register(new BlockItem(builder(), Blocks.BLUE_CANDLE)); + public static final Item BROWN_CANDLE = register(new BlockItem(builder(), Blocks.BROWN_CANDLE)); + public static final Item GREEN_CANDLE = register(new BlockItem(builder(), Blocks.GREEN_CANDLE)); + public static final Item RED_CANDLE = register(new BlockItem(builder(), Blocks.RED_CANDLE)); + public static final Item BLACK_CANDLE = register(new BlockItem(builder(), Blocks.BLACK_CANDLE)); + public static final Item SMALL_AMETHYST_BUD = register(new BlockItem(builder(), Blocks.SMALL_AMETHYST_BUD)); + public static final Item MEDIUM_AMETHYST_BUD = register(new BlockItem(builder(), Blocks.MEDIUM_AMETHYST_BUD)); + public static final Item LARGE_AMETHYST_BUD = register(new BlockItem(builder(), Blocks.LARGE_AMETHYST_BUD)); + public static final Item AMETHYST_CLUSTER = register(new BlockItem(builder(), Blocks.AMETHYST_CLUSTER)); + public static final Item POINTED_DRIPSTONE = register(new BlockItem(builder(), Blocks.POINTED_DRIPSTONE)); + public static final Item OCHRE_FROGLIGHT = register(new BlockItem(builder(), Blocks.OCHRE_FROGLIGHT)); + public static final Item VERDANT_FROGLIGHT = register(new BlockItem(builder(), Blocks.VERDANT_FROGLIGHT)); + public static final Item PEARLESCENT_FROGLIGHT = register(new BlockItem(builder(), Blocks.PEARLESCENT_FROGLIGHT)); + public static final Item FROGSPAWN = register(new BlockItem(builder(), Blocks.FROGSPAWN)); public static final Item ECHO_SHARD = register(new Item("echo_shard", builder())); public static final Item BRUSH = register(new Item("brush", builder().stackSize(1).maxDamage(64))); public static final Item NETHERITE_UPGRADE_SMITHING_TEMPLATE = register(new Item("netherite_upgrade_smithing_template", builder())); @@ -1346,26 +1347,26 @@ 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 COPPER_GRATE = register(new BlockItem(builder(), Blocks.COPPER_GRATE)); + public static final Item EXPOSED_COPPER_GRATE = register(new BlockItem(builder(), Blocks.EXPOSED_COPPER_GRATE)); + public static final Item WEATHERED_COPPER_GRATE = register(new BlockItem(builder(), Blocks.WEATHERED_COPPER_GRATE)); + public static final Item OXIDIZED_COPPER_GRATE = register(new BlockItem(builder(), Blocks.OXIDIZED_COPPER_GRATE)); + public static final Item WAXED_COPPER_GRATE = register(new BlockItem(builder(), Blocks.WAXED_COPPER_GRATE)); + public static final Item WAXED_EXPOSED_COPPER_GRATE = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_COPPER_GRATE)); + public static final Item WAXED_WEATHERED_COPPER_GRATE = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_COPPER_GRATE)); + public static final Item WAXED_OXIDIZED_COPPER_GRATE = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_COPPER_GRATE)); + public static final Item COPPER_BULB = register(new BlockItem(builder(), Blocks.COPPER_BULB)); + public static final Item EXPOSED_COPPER_BULB = register(new BlockItem(builder(), Blocks.EXPOSED_COPPER_BULB)); + public static final Item WEATHERED_COPPER_BULB = register(new BlockItem(builder(), Blocks.WEATHERED_COPPER_BULB)); + public static final Item OXIDIZED_COPPER_BULB = register(new BlockItem(builder(), Blocks.OXIDIZED_COPPER_BULB)); + public static final Item WAXED_COPPER_BULB = register(new BlockItem(builder(), Blocks.WAXED_COPPER_BULB)); + public static final Item WAXED_EXPOSED_COPPER_BULB = register(new BlockItem(builder(), Blocks.WAXED_EXPOSED_COPPER_BULB)); + public static final Item WAXED_WEATHERED_COPPER_BULB = register(new BlockItem(builder(), Blocks.WAXED_WEATHERED_COPPER_BULB)); + public static final Item WAXED_OXIDIZED_COPPER_BULB = register(new BlockItem(builder(), Blocks.WAXED_OXIDIZED_COPPER_BULB)); + public static final Item TRIAL_SPAWNER = register(new BlockItem(builder(), Blocks.TRIAL_SPAWNER)); 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 VAULT = register(new BlockItem(builder(), Blocks.VAULT)); public static final Item OMINOUS_BOTTLE = register(new Item("ominous_bottle", builder())); public static final Item BREEZE_ROD = register(new Item("breeze_rod", 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 6c2678db9..b53843882 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 @@ -35,6 +35,7 @@ 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.level.block.type.Block; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.registry.JavaRegistry; @@ -199,8 +200,8 @@ public class BannerItem extends BlockItem { return null; } - public BannerItem(String javaIdentifier, Builder builder) { - super(javaIdentifier, builder); + public BannerItem(Builder builder, Block block, Block... otherBlocks) { + super(builder, block, otherBlocks); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/item/type/BlockItem.java b/core/src/main/java/org/geysermc/geyser/item/type/BlockItem.java index 0dbf0971a..30a31a100 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/BlockItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/BlockItem.java @@ -25,11 +25,26 @@ package org.geysermc.geyser.item.type; -/** - * TODO needed? - */ +import org.geysermc.geyser.level.block.type.Block; + public class BlockItem extends Item { - public BlockItem(String javaIdentifier, Builder builder) { + public BlockItem(Builder builder, Block block, Block... otherBlocks) { + super(block.javaIdentifier().value(), builder); + + // Ensure this item can be looked up by its block(s) + registerBlock(block, this); + for (Block otherBlock : otherBlocks) { + registerBlock(otherBlock, this); + } + } + + // Use this constructor if the item name is not the same as its primary block + public BlockItem(String javaIdentifier, Builder builder, Block block, Block... otherBlocks) { super(javaIdentifier, builder); + + registerBlock(block, this); + for (Block otherBlock : otherBlocks) { + registerBlock(otherBlock, this); + } } } 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 2631bf9be..578ba4063 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 @@ -27,6 +27,7 @@ package org.geysermc.geyser.item.type; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.nbt.NbtType; +import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; @@ -38,8 +39,8 @@ import java.util.List; public class DecoratedPotItem extends BlockItem { - public DecoratedPotItem(String javaIdentifier, Builder builder) { - super(javaIdentifier, builder); + public DecoratedPotItem(Builder builder, Block block, Block... otherBlocks) { + super(builder, block, otherBlocks); } @Override 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 fc4fda07c..1ec410eaf 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 @@ -35,6 +35,7 @@ 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.level.block.type.Block; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.session.GeyserSession; @@ -49,20 +50,12 @@ import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponen import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemEnchantments; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; public class Item { - /** - * This is a map from Java-only enchantments to their translation keys so that we can - * map these enchantments to Bedrock clients, since they don't actually exist there. - */ - private static final Map ENCHANTMENT_TRANSLATION_KEYS = Map.of( - Enchantment.JavaEnchantment.SWEEPING_EDGE, "enchantment.minecraft.sweeping", - Enchantment.JavaEnchantment.DENSITY, "enchantment.minecraft.density", - Enchantment.JavaEnchantment.BREACH, "enchantment.minecraft.breach", - Enchantment.JavaEnchantment.WIND_BURST, "enchantment.minecraft.wind_burst"); - + private static final Map BLOCK_TO_ITEM = new HashMap<>(); private final String javaIdentifier; private int javaId = -1; private final int stackSize; @@ -233,6 +226,16 @@ public class Item { // } } + /** + * This is a map from Java-only enchantments to their translation keys so that we can + * map these enchantments to Bedrock clients, since they don't actually exist there. + */ + private static final Map ENCHANTMENT_TRANSLATION_KEYS = Map.of( + Enchantment.JavaEnchantment.SWEEPING_EDGE, "enchantment.minecraft.sweeping", + Enchantment.JavaEnchantment.DENSITY, "enchantment.minecraft.density", + Enchantment.JavaEnchantment.BREACH, "enchantment.minecraft.breach", + Enchantment.JavaEnchantment.WIND_BURST, "enchantment.minecraft.wind_burst"); + protected final @Nullable NbtMap remapEnchantment(GeyserSession session, int enchantId, int level, BedrockItemBuilder builder) { // TODO verify // TODO streamline Enchantment process @@ -281,6 +284,18 @@ public class Item { '}'; } + /** + * @return the block associated with this item, or air if nothing + */ + @NonNull + public static Item byBlock(Block block) { + return BLOCK_TO_ITEM.getOrDefault(block, Items.AIR); + } + + protected static void registerBlock(Block block, Item item) { + BLOCK_TO_ITEM.put(block, item); + } + public static Builder builder() { return new 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 0cdbe70f1..86572d60c 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 @@ -27,6 +27,7 @@ package org.geysermc.geyser.item.type; import com.github.steveice10.mc.auth.data.GameProfile; import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.MinecraftLocale; @@ -34,9 +35,9 @@ 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) { - super(javaIdentifier, builder); +public class PlayerHeadItem extends BlockItem { + public PlayerHeadItem(Builder builder, Block block, Block... otherBlocks) { + super(builder, block, otherBlocks); } @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 6b2d589d6..a539fa739 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 @@ -30,6 +30,7 @@ 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.level.block.type.Block; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; @@ -42,8 +43,8 @@ import java.util.ArrayList; import java.util.List; public class ShulkerBoxItem extends BlockItem { - public ShulkerBoxItem(String javaIdentifier, Builder builder) { - super(javaIdentifier, builder); + public ShulkerBoxItem(Builder builder, Block block, Block... otherBlocks) { + super(builder, block, otherBlocks); } @Override 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 a64e5c1c8..9b390f6ee 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 @@ -249,25 +249,6 @@ public final class BlockStateValues { return ALL_CAULDRONS.contains(state); } - /** - * All double chest values are part of the block state in Java and part of the block entity tag in Bedrock. - * This gives the DoubleChestValue that can be calculated into the final tag. - * - * @return The map of all DoubleChestValues. - */ - public static Int2ObjectMap getDoubleChestValues() { - return DOUBLE_CHEST_VALUES; - } - - /** - * Get the Int2ObjectMap of flower pot block states to containing plant - * - * @return Int2ObjectMap of flower pot values - */ - public static Int2ObjectMap getFlowerPotValues() { - return FLOWER_POT_VALUES; - } - /** * @return a set of all forward-facing jigsaws, to use as a fallback if NBT is missing. */ @@ -282,26 +263,6 @@ public final class BlockStateValues { return LECTERN_BOOK_STATES; } - /** - * The note that noteblocks output when hit is part of the block state in Java but sent as a BlockEventPacket in Bedrock. - * This gives an integer pitch that Bedrock can use. - * - * @param state BlockState of the block - * @return note block note integer or -1 if not present - */ - public static int getNoteblockPitch(int state) { - return NOTEBLOCK_PITCHES.getOrDefault(state, -1); - } - - /** - * Get the Int2BooleanMap showing if a piston block state is extended or not. - * - * @return the Int2BooleanMap of piston extensions. - */ - public static Int2BooleanMap getPistonValues() { - return PISTON_VALUES; - } - public static boolean isStickyPiston(int blockState) { return STICKY_PISTONS.contains(blockState); } @@ -435,16 +396,6 @@ 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/level/block/Blocks.java b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java index 142708dd9..485d52161 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java @@ -82,7 +82,7 @@ public final class Blocks { .intState(STAGE, 0, 1) .booleanState(WATERLOGGED))); public static final Block BEDROCK = register(new Block("bedrock", builder().destroyTime(-1.0f))); - public static final Block WATER = register(new Block("water", builder().destroyTime(100.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block WATER = register(new WaterBlock("water", builder().destroyTime(100.0f).pushReaction(PistonBehavior.DESTROY) .intState(LEVEL, 0, 15))); public static final Block LAVA = register(new Block("lava", builder().destroyTime(100.0f).pushReaction(PistonBehavior.DESTROY) .intState(LEVEL, 0, 15))); @@ -379,7 +379,7 @@ public final class Blocks { .booleanState(UP) .booleanState(WEST))); public static final Block SOUL_FIRE = register(new Block("soul_fire", builder().pushReaction(PistonBehavior.DESTROY))); - public static final Block SPAWNER = register(new Block("spawner", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(5.0f))); + public static final Block SPAWNER = register(new SpawnerBlock("spawner", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(5.0f))); public static final Block OAK_STAIRS = register(new Block("oak_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") @@ -403,7 +403,7 @@ public final class Blocks { .intState(AGE_7, 0, 7))); public static final Block FARMLAND = register(new Block("farmland", builder().destroyTime(0.6f) .intState(MOISTURE, 0, 7))); - public static final Block FURNACE = register(new Block("furnace", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(3.5f) + public static final Block FURNACE = register(new FurnaceBlock("furnace", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(LIT))); public static final Block OAK_SIGN = register(new Block("oak_sign", builder().setBlockEntity().destroyTime(1.0f) @@ -823,10 +823,10 @@ public final class Blocks { .booleanState(HAS_BOTTLE_1) .booleanState(HAS_BOTTLE_2))); public static final Block CAULDRON = register(new CauldronBlock("cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); - public static final Block WATER_CAULDRON = register(new Block("water_cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f) + public static final Block WATER_CAULDRON = register(new CauldronBlock("water_cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .intState(LEVEL_CAULDRON, 1, 3))); - public static final Block LAVA_CAULDRON = register(new Block("lava_cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); - public static final Block POWDER_SNOW_CAULDRON = register(new Block("powder_snow_cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f) + public static final Block LAVA_CAULDRON = register(new CauldronBlock("lava_cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); + public static final Block POWDER_SNOW_CAULDRON = register(new CauldronBlock("powder_snow_cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .intState(LEVEL_CAULDRON, 1, 3))); public static final Block END_PORTAL = register(new Block("end_portal", builder().setBlockEntity().destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK))); public static final Block END_PORTAL_FRAME = register(new Block("end_portal_frame", builder().destroyTime(-1.0f) @@ -2179,7 +2179,7 @@ public final class Blocks { public static final Block BEEHIVE = register(new Block("beehive", builder().setBlockEntity().destroyTime(0.6f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .intState(LEVEL_HONEY, 0, 5))); - public static final Block HONEY_BLOCK = register(new Block("honey_block", builder())); + public static final Block HONEY_BLOCK = register(new HoneyBlock("honey_block", builder())); public static final Block HONEYCOMB_BLOCK = register(new Block("honeycomb_block", builder().destroyTime(0.6f))); public static final Block NETHERITE_BLOCK = register(new Block("netherite_block", builder().requiresCorrectToolForDrops().destroyTime(50.0f))); public static final Block ANCIENT_DEBRIS = register(new Block("ancient_debris", builder().requiresCorrectToolForDrops().destroyTime(30.0f))); diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/Property.java b/core/src/main/java/org/geysermc/geyser/level/block/property/Property.java index da68c54e4..ca5f62daa 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/property/Property.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/property/Property.java @@ -32,6 +32,10 @@ public class Property> { this.name = name; } + public String name() { + return name; + } + @Override public String toString() { return getClass().getSimpleName() + "[" + name + "]"; diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java b/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java index 3114f31f9..491894a35 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java @@ -25,21 +25,24 @@ package org.geysermc.geyser.level.block.type; -import it.unimi.dsi.fastutil.Pair; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap; import it.unimi.dsi.fastutil.objects.Reference2ObjectMap; +import it.unimi.dsi.fastutil.objects.Reference2ObjectMaps; +import net.kyori.adventure.key.Key; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.level.block.Blocks; +import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.level.block.property.Property; import org.geysermc.geyser.level.physics.PistonBehavior; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.mcprotocollib.protocol.data.game.Identifier; +import org.intellij.lang.annotations.Subst; import java.util.*; import java.util.stream.Stream; @@ -47,20 +50,21 @@ import java.util.stream.Stream; public class Block { public static final int JAVA_AIR_ID = 0; - private final String javaIdentifier; + private final Key javaIdentifier; private final boolean requiresCorrectToolForDrops; private final boolean hasBlockEntity; private final float destroyTime; private final @NonNull PistonBehavior pushReaction; + protected Item item = null; private int javaId = -1; - public Block(String javaIdentifier, Builder builder) { - this.javaIdentifier = Identifier.formalize(javaIdentifier).intern(); + public Block(@Subst("empty") String javaIdentifier, Builder builder) { + this.javaIdentifier = Key.key(javaIdentifier); this.requiresCorrectToolForDrops = builder.requiresCorrectToolForDrops; this.hasBlockEntity = builder.hasBlockEntity; this.destroyTime = builder.destroyTime; this.pushReaction = builder.pushReaction; - builder.build(this); + processStates(builder.build(this)); } public void updateBlock(GeyserSession session, BlockState state, Vector3i position) { @@ -114,7 +118,8 @@ public class Block { UpdateBlockPacket waterPacket = new UpdateBlockPacket(); waterPacket.setDataLayer(1); waterPacket.setBlockPosition(position); - if (BlockRegistries.WATERLOGGED.get().get(state.javaId())) { + Boolean waterlogged = state.getValue(Properties.WATERLOGGED); + if (waterlogged == Boolean.TRUE) { waterPacket.setDefinition(session.getBlockMappings().getBedrockWater()); } else { waterPacket.setDefinition(session.getBlockMappings().getBedrockAir()); @@ -129,7 +134,21 @@ public class Block { } } - public String javaIdentifier() { + public Item asItem() { + if (this.item == null) { + return this.item = Item.byBlock(this); + } + return this.item; + } + + /** + * A list of BlockStates is created pertaining to this block. Do we need any of them? If so, override this method. + */ + protected void processStates(List states) { + } + + @NonNull + public Key javaIdentifier() { return javaIdentifier; } @@ -163,7 +182,7 @@ public class Block { @Override public String toString() { - return "Item{" + + return "Block{" + "javaIdentifier='" + javaIdentifier + '\'' + ", javaId=" + javaId + '}'; @@ -229,14 +248,27 @@ public class Block { return this; } - private void build(Block block) { + private List build(Block block) { if (states.isEmpty()) { - BlockRegistries.BLOCK_STATES.get().add(new BlockState(block, BlockRegistries.BLOCK_STATES.get().size())); + BlockState state = new BlockState(block, BlockRegistries.BLOCK_STATES.get().size()); + BlockRegistries.BLOCK_STATES.get().add(state); + return List.of(state); + } else if (states.size() == 1) { + // We can optimize because we don't need to worry about combinations + Map.Entry, List>> property = this.states.entrySet().stream().findFirst().orElseThrow(); + List states = new ArrayList<>(property.getValue().size()); + property.getValue().forEach(value -> { + Reference2ObjectMap, Comparable> propertyMap = Reference2ObjectMaps.singleton(property.getKey(), value); + BlockState state = new BlockState(block, BlockRegistries.BLOCK_STATES.get().size(), propertyMap); + BlockRegistries.BLOCK_STATES.get().add(state); + states.add(state); + }); + return states; } else { // Think of this stream as another list containing, at the start, one empty list. // It's two collections. Not a stream from the empty list. - Stream, Comparable>>> stream = Stream.of(Collections.emptyList()); - for (var state : this.states.entrySet()) { + Stream>> stream = Stream.of(Collections.emptyList()); + for (var values : this.states.values()) { // OK, so here's how I understand this works. Because this was staring at vanilla Java code trying // to figure out exactly how it works so we don't have any discrepencies. // For each existing pair in the list, a new list is created, adding one of the new values. @@ -247,24 +279,29 @@ public class Block { // or it may be populated if this is not the first property. // We're about to create a new stream, each with a new list, // for every previous property - state.getValue().stream().map(value -> { + values.stream().map(value -> { var newProperties = new ArrayList<>(aPreviousPropertiesList); - newProperties.add(Pair.of(state.getKey(), value)); + newProperties.add(value); return newProperties; })); } + List states = new ArrayList<>(); // Now we have a list of Pairs. Each list is a block state! // If we have two boolean properties: up [true/false] and down [true/false], // We'll see [up=true,down=true], [up=false,down=true], [up=true,down=false], [up=false,down=false] - stream.forEach(properties -> { - Reference2ObjectMap, Comparable> propertyMap = new Reference2ObjectArrayMap<>(properties.size()); - for (int i = 0; i < properties.size(); i++) { - Pair, Comparable> property = properties.get(i); - propertyMap.put(property.key(), property.value()); - } - BlockRegistries.BLOCK_STATES.get().add(new BlockState(block, BlockRegistries.BLOCK_STATES.get().size(), propertyMap)); + List>> result = stream.toList(); + // Ensure each block state shares the same key array. Creating a keySet here shouldn't be an issue since + // this states map should be removed after build. + Property[] keys = this.states.keySet().toArray(new Property[0]); + result.forEach(properties -> { + Comparable[] values = properties.toArray(new Comparable[0]); + Reference2ObjectMap, Comparable> propertyMap = new Reference2ObjectArrayMap<>(keys, values); + BlockState state = new BlockState(block, BlockRegistries.BLOCK_STATES.get().size(), propertyMap); + BlockRegistries.BLOCK_STATES.get().add(state); + states.add(state); }); + return states; } } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java index de4806efa..cb375eaf9 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java @@ -30,6 +30,8 @@ import it.unimi.dsi.fastutil.objects.Reference2ObjectMaps; import org.geysermc.geyser.level.block.property.Property; import org.geysermc.geyser.registry.BlockRegistries; +import java.util.Locale; + public final class BlockState { private final Block block; private final int javaId; @@ -62,12 +64,25 @@ public final class BlockState { return this.block == block; } + @Override + public String toString() { + if (this.states.isEmpty()) { + return this.block.javaIdentifier().toString(); + } + return this.block.javaIdentifier().toString() + "[" + paramsToString() + "]"; + } + private String paramsToString() { StringBuilder builder = new StringBuilder(); var it = this.states.entrySet().iterator(); while (it.hasNext()) { var entry = it.next(); - builder.append(entry.getKey()).append("=").append(entry.getValue()); + builder.append(entry.getKey().name()) + .append("=") + .append(entry.getValue().toString().toLowerCase(Locale.ROOT)); // lowercase covers enums + if (it.hasNext()) { + builder.append(","); + } } return builder.toString(); } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/FlowerPotBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/FlowerPotBlock.java index 8c911ad97..53d0b1ec1 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/FlowerPotBlock.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/FlowerPotBlock.java @@ -68,7 +68,7 @@ public class FlowerPotBlock extends Block implements BedrockChunkWantsBlockEntit if (this.flower != Blocks.AIR) { // Get the Bedrock CompoundTag of the block. // This is where we need to store the *Java* name because Bedrock has six minecraft:sapling blocks with different block states. - NbtMap plant = session.getBlockMappings().getFlowerPotBlocks().get(this.flower.javaIdentifier()); + NbtMap plant = session.getBlockMappings().getFlowerPotBlocks().get(this.flower.javaIdentifier().asString()); if (plant != null) { tagBuilder.putCompound("PlantBlock", plant.toBuilder().build()); } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/FurnaceBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/FurnaceBlock.java new file mode 100644 index 000000000..2b898e089 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/FurnaceBlock.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 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.level.block.type; + +import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.geyser.level.physics.Direction; + +import java.util.List; + +public class FurnaceBlock extends Block { + private static BlockState LIT; + private static BlockState UNLIT; + + public FurnaceBlock(String javaIdentifier, Builder builder) { + super(javaIdentifier, builder); + } + + @Override + protected void processStates(List states) { + LIT = states.stream() + .filter(state -> state.getValue(Properties.HORIZONTAL_FACING) == Direction.NORTH + && state.getValue(Properties.LIT)) + .findFirst().orElseThrow(); + UNLIT = states.stream() + .filter(state -> state.getValue(Properties.HORIZONTAL_FACING) == Direction.NORTH + && !state.getValue(Properties.LIT)) + .findFirst().orElseThrow(); + } + + public static BlockState state(boolean lit) { + return lit ? LIT : UNLIT; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/HoneyBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/HoneyBlock.java new file mode 100644 index 000000000..73c4d02aa --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/HoneyBlock.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 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.level.block.type; + +import java.util.List; + +public class HoneyBlock extends Block { + private static BlockState STATE; + + public HoneyBlock(String javaIdentifier, Builder builder) { + super(javaIdentifier, builder); + } + + @Override + protected void processStates(List states) { + STATE = states.get(0); + } + + public static BlockState state() { + return STATE; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/SpawnerBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/SpawnerBlock.java new file mode 100644 index 000000000..2103fe6e5 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/SpawnerBlock.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 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.level.block.type; + +import java.util.List; + +public class SpawnerBlock extends Block { + private static BlockState STATE; + + public SpawnerBlock(String javaIdentifier, Builder builder) { + super(javaIdentifier, builder); + } + + @Override + protected void processStates(List states) { + STATE = states.get(0); + } + + public static BlockState state() { + return STATE; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/WaterBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/WaterBlock.java new file mode 100644 index 000000000..801a7f9e7 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/WaterBlock.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 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.level.block.type; + +import java.util.List; + +public class WaterBlock extends Block { + private static BlockState LEVEL_0; + + public WaterBlock(String javaIdentifier, Builder builder) { + super(javaIdentifier, builder); + } + + @Override + protected void processStates(List states) { + super.processStates(states); + } +} 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 416ab7793..a18ffff7d 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java +++ b/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java @@ -147,6 +147,7 @@ public class BlockRegistries { CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.CUSTOM_REGISTRATION); BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.INIT_BEDROCK); BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.POST_INIT); + System.out.println("Block registries loaded"); } public static void init() { 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 54d013140..7f0d9013a 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/Registries.java +++ b/core/src/main/java/org/geysermc/geyser/registry/Registries.java @@ -204,5 +204,6 @@ public final class Registries { biomesNbt.put(key, value.build()); } BIOMES_NBT.set(biomesNbt.build()); + System.out.println("Registries loaded"); } } 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 7cf39b6d7..2cd7f82d6 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 @@ -106,7 +106,7 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader, CollisionInfo> annotationMap, int collisionIndex, List collisionList) { - String blockName = state.block().javaIdentifier().substring("minecraft:".length()); + String blockName = state.block().javaIdentifier().value(); for (Map.Entry, CollisionInfo> collisionRemappers : annotationMap.entrySet()) { Class type = collisionRemappers.getKey(); 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 66301cef2..0180fc8b7 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 @@ -50,10 +50,12 @@ 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.item.type.Item; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.level.physics.PistonBehavior; import org.geysermc.geyser.registry.BlockRegistries; +import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.BlockMapping; import org.geysermc.geyser.registry.type.BlockMappings; import org.geysermc.geyser.registry.type.GeyserBedrockBlock; @@ -391,7 +393,7 @@ public final class BlockRegistryPopulator { throw new AssertionError("Unable to load Java block mappings", e); } - JAVA_BLOCKS_SIZE = blocksJson.size(); + JAVA_BLOCKS_SIZE = BlockRegistries.BLOCK_STATES.get().size(); 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(); @@ -409,12 +411,6 @@ public final class BlockRegistryPopulator { Deque cleanIdentifiers = new ArrayDeque<>(); int javaRuntimeId = -1; - int furnaceRuntimeId = -1; - int furnaceLitRuntimeId = -1; - int honeyBlockRuntimeId = -1; - int slimeBlockRuntimeId = -1; - int spawnerRuntimeId = -1; - int uniqueJavaId = -1; int waterRuntimeId = -1; Iterator> blocksIterator = blocksJson.fields(); while (blocksIterator.hasNext()) { @@ -422,7 +418,6 @@ public final class BlockRegistryPopulator { Map.Entry entry = blocksIterator.next(); String javaId = entry.getKey(); - // TODO fix this, (no block should have a null hardness) BlockMapping.BlockMappingBuilder builder = BlockMapping.builder(); JsonNode pickItemNode = entry.getValue().get("pick_item"); @@ -443,7 +438,6 @@ public final class BlockRegistryPopulator { String bedrockIdentifier = entry.getValue().get("bedrock_identifier").asText(); if (!cleanJavaIdentifier.equals(cleanIdentifiers.peekLast())) { - uniqueJavaId++; cleanIdentifiers.add(cleanJavaIdentifier.intern()); } @@ -456,50 +450,11 @@ public final class BlockRegistryPopulator { // 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()); - if (javaId.startsWith("minecraft:furnace[facing=north")) { - if (javaId.contains("lit=true")) { - furnaceLitRuntimeId = javaRuntimeId; - } else { - furnaceRuntimeId = javaRuntimeId; - } - - } else if (javaId.startsWith("minecraft:spawner")) { - spawnerRuntimeId = javaRuntimeId; - - } else if ("minecraft:water[level=0]".equals(javaId)) { + if ("minecraft:water[level=0]".equals(javaId)) { waterRuntimeId = javaRuntimeId; - } else if (javaId.equals("minecraft:honey_block")) { - honeyBlockRuntimeId = javaRuntimeId; - } else if (javaId.equals("minecraft:slime_block")) { - slimeBlockRuntimeId = javaRuntimeId; } } - if (furnaceRuntimeId == -1) { - throw new AssertionError("Unable to find furnace in palette"); - } - BlockStateValues.JAVA_FURNACE_ID = furnaceRuntimeId; - - if (furnaceLitRuntimeId == -1) { - throw new AssertionError("Unable to find lit furnace in palette"); - } - BlockStateValues.JAVA_FURNACE_LIT_ID = furnaceLitRuntimeId; - - if (honeyBlockRuntimeId == -1) { - throw new AssertionError("Unable to find honey block in palette"); - } - BlockStateValues.JAVA_HONEY_BLOCK_ID = honeyBlockRuntimeId; - - if (slimeBlockRuntimeId == -1) { - throw new AssertionError("Unable to find slime block in palette"); - } - BlockStateValues.JAVA_SLIME_BLOCK_ID = slimeBlockRuntimeId; - - if (spawnerRuntimeId == -1) { - throw new AssertionError("Unable to find spawner in palette"); - } - BlockStateValues.JAVA_SPAWNER_ID = spawnerRuntimeId; - if (waterRuntimeId == -1) { throw new AssertionError("Unable to find Java water in palette"); } @@ -534,12 +489,20 @@ public final class BlockRegistryPopulator { builder.setBlockEntity(); } String cleanJavaIdentifier = BlockUtils.getCleanIdentifier(javaBlockState.identifier()); - Block block = new Block(cleanJavaIdentifier, builder); + String pickItem = javaBlockState.pickItem(); + Block block = new Block(cleanJavaIdentifier, builder) { + @Override + public Item asItem() { + if (this.item == null) { + return Registries.JAVA_ITEM_IDENTIFIERS.get(pickItem); + } + return this.item; + } + }; String bedrockIdentifier = customBlockState.block().identifier(); if (!cleanJavaIdentifier.equals(cleanIdentifiers.peekLast())) { - uniqueJavaId++; cleanIdentifiers.add(cleanJavaIdentifier.intern()); } 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 d6ee55965..0520924f8 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 @@ -28,7 +28,6 @@ package org.geysermc.geyser.registry.type; import lombok.Builder; import lombok.Value; import org.checkerframework.checker.nullness.qual.Nullable; -import org.geysermc.geyser.util.BlockUtils; @Builder @Value @@ -37,42 +36,8 @@ public class BlockMapping { String javaIdentifier; - boolean canBreakWithHand; @Nullable String pickItem; boolean isBlockEntity; boolean isNonVanilla; - - /** - * @return the identifier without the additional block states - */ - public String getCleanJavaIdentifier() { - return BlockUtils.getCleanIdentifier(javaIdentifier); - } - - /** - * @return the corresponding Java identifier for this item - */ - public String getItemIdentifier() { - if (pickItem != null && !pickItem.equals("minecraft:air")) { - // Spawners can have air as their pick item which we are not interested in. - return pickItem; - } - - return getCleanJavaIdentifier(); - } - - /** - * Get the item a Java client would receive when pressing - * the Pick Block key on a specific Java block state. - * - * @return The Java identifier of the item - */ - public String getPickItem() { - if (pickItem != null) { - return pickItem; - } - - return getCleanJavaIdentifier(); - } } diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 144cd9f27..c85c0fd28 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -97,6 +97,7 @@ import org.geysermc.geyser.inventory.PlayerInventory; import org.geysermc.geyser.inventory.recipe.GeyserRecipe; import org.geysermc.geyser.inventory.recipe.GeyserStonecutterData; import org.geysermc.geyser.item.Items; +import org.geysermc.geyser.item.type.BlockItem; import org.geysermc.geyser.level.JavaDimension; import org.geysermc.geyser.level.WorldManager; import org.geysermc.geyser.level.physics.CollisionManager; @@ -349,7 +350,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { private Vector3i lastBlockPlacePosition; @Setter - private String lastBlockPlacedId; + private BlockItem lastBlockPlaced; @Setter private boolean interacting; diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/AbstractBlockInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/AbstractBlockInventoryTranslator.java index ac6e9870e..2dfa2a85a 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/AbstractBlockInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/AbstractBlockInventoryTranslator.java @@ -30,6 +30,7 @@ import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.holder.BlockInventoryHolder; import org.geysermc.geyser.inventory.holder.InventoryHolder; import org.geysermc.geyser.inventory.updater.InventoryUpdater; +import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.session.GeyserSession; /** @@ -44,10 +45,10 @@ public abstract class AbstractBlockInventoryTranslator extends BaseInventoryTran * @param javaBlockIdentifier a Java block identifier that is used as a temporary block * @param containerType the container type of this inventory * @param updater updater - * @param additionalValidBlocks any other block identifiers that can safely use this inventory without a fake block + * @param additionalValidBlocks any other blocks that can safely use this inventory without a fake block */ public AbstractBlockInventoryTranslator(int size, String javaBlockIdentifier, ContainerType containerType, InventoryUpdater updater, - String... additionalValidBlocks) { + Block... additionalValidBlocks) { super(size); this.holder = new BlockInventoryHolder(javaBlockIdentifier, containerType, additionalValidBlocks); this.updater = updater; 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 2da51a0eb..705fac362 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 @@ -37,6 +37,7 @@ import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.PlayerInventory; import org.geysermc.geyser.inventory.updater.AnvilInventoryUpdater; +import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; @@ -45,7 +46,7 @@ import java.util.Objects; public class AnvilInventoryTranslator extends AbstractBlockInventoryTranslator { public AnvilInventoryTranslator() { super(3, "minecraft:anvil[facing=north]", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.ANVIL, AnvilInventoryUpdater.INSTANCE, - "minecraft:chipped_anvil", "minecraft:damaged_anvil"); + Blocks.CHIPPED_ANVIL, Blocks.DAMAGED_ANVIL); } @Override 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 2a80161c0..f47a367d8 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 @@ -32,6 +32,7 @@ import org.geysermc.geyser.inventory.Generic3X3Container; import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.PlayerInventory; import org.geysermc.geyser.inventory.updater.ContainerInventoryUpdater; +import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; @@ -41,7 +42,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; public class Generic3X3InventoryTranslator extends AbstractBlockInventoryTranslator { public Generic3X3InventoryTranslator() { super(9, "minecraft:dispenser[facing=north,triggered=false]", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.DISPENSER, ContainerInventoryUpdater.INSTANCE, - "minecraft:dropper"); + Blocks.DROPPER); } @Override 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 795eba101..72f5260a0 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 @@ -52,14 +52,14 @@ public class ShulkerInventoryTranslator extends AbstractBlockInventoryTranslator } @Override - protected void setCustomName(GeyserSession session, Vector3i position, Inventory inventory, int javaBlockState) { + protected void setCustomName(GeyserSession session, Vector3i position, Inventory inventory, BlockState javaBlockState) { NbtMapBuilder tag = NbtMap.builder() .putInt("x", position.getX()) .putInt("y", position.getY()) .putInt("z", position.getZ()) .putString("CustomName", inventory.getTitle()); // Don't reset facing property - shulkerBoxTranslator.translateTag(session, tag, null, BlockState.of(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/inventory/chest/SingleChestInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/chest/SingleChestInventoryTranslator.java index d09e7e990..e18096862 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/chest/SingleChestInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/chest/SingleChestInventoryTranslator.java @@ -29,15 +29,17 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.holder.BlockInventoryHolder; import org.geysermc.geyser.inventory.holder.InventoryHolder; +import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.session.GeyserSession; public class SingleChestInventoryTranslator extends ChestInventoryTranslator { private final InventoryHolder holder; + // TODO add barrel??? public SingleChestInventoryTranslator(int size) { super(size, 27); this.holder = new BlockInventoryHolder("minecraft:chest[facing=north,type=single,waterlogged=false]", ContainerType.CONTAINER, - "minecraft:ender_chest", "minecraft:trapped_chest") { + Blocks.ENDER_CHEST, Blocks.TRAPPED_CHEST) { @Override protected boolean isValidBlock(String[] javaBlockString) { if (javaBlockString[0].equals("minecraft:ender_chest")) { 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 14282228b..ca8679319 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 @@ -30,6 +30,7 @@ import it.unimi.dsi.fastutil.objects.*; import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.level.block.type.BlockState; +import org.geysermc.geyser.level.block.type.HoneyBlock; import org.geysermc.geyser.level.block.type.PistonBlock; import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType; import org.cloudburstmc.math.vector.Vector3d; @@ -98,7 +99,7 @@ public class PistonBlockEntity { static { // Create a ~1 x ~0.5 x ~1 bounding box above the honey block - BlockCollision blockCollision = BlockRegistries.COLLISIONS.get(BlockStateValues.JAVA_HONEY_BLOCK_ID); + BlockCollision blockCollision = BlockRegistries.COLLISIONS.get(HoneyBlock.state().javaId()); if (blockCollision == null) { throw new RuntimeException("Failed to find honey block collision"); } @@ -622,11 +623,11 @@ public class PistonBlockEntity { } placedFinalBlocks = true; Vector3i movement = getMovement(); - attachedBlocks.forEach((blockPos, javaId) -> { + attachedBlocks.forEach((blockPos, state) -> { blockPos = blockPos.add(movement); // Don't place blocks that collide with the player if (!SOLID_BOUNDING_BOX.checkIntersection(blockPos.toDouble(), session.getCollisionManager().getPlayerBoundingBox())) { - ChunkUtils.updateBlock(session, javaId, blockPos); + ChunkUtils.updateBlock(session, state, blockPos); } }); if (action == PistonValueType.PUSHING) { 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 507d67ba5..be3af2061 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 @@ -29,11 +29,10 @@ import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.packet.BlockPickRequestPacket; import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.type.ItemFrameEntity; -import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.item.Items; +import org.geysermc.geyser.level.block.Blocks; +import org.geysermc.geyser.level.block.type.BannerBlock; import org.geysermc.geyser.level.block.type.Block; -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.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; @@ -46,10 +45,10 @@ public class BedrockBlockPickRequestTranslator extends PacketTranslator session.ensureInEventLoop(() -> { if (components == null) { - pickItem(session, blockMapping); + pickItem(session, blockToPick); return; } - // 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, components); + ItemStack itemStack = new ItemStack(blockToPick.asItem().javaId(), 1, components); InventoryUtils.findOrCreateItem(session, itemStack); })); return; } - pickItem(session, blockMapping); + pickItem(session, blockToPick); } - private void pickItem(GeyserSession session, BlockMapping blockToPick) { - InventoryUtils.findOrCreateItem(session, blockToPick.getPickItem()); + private void pickItem(GeyserSession session, Block block) { + InventoryUtils.findOrCreateItem(session, block.asItem()); } } 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 9c6a1cb56..78745aeb8 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 @@ -355,9 +355,9 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator * 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 + * @param item the Java item to search/select for */ - public static void findOrCreateItem(GeyserSession session, String itemName) { + public static void findOrCreateItem(GeyserSession session, Item item) { // Get the inventory to choose a slot to pick PlayerInventory inventory = session.getPlayerInventory(); - if (itemName.equals("minecraft:air")) { + if (item == Items.AIR) { return; } @@ -326,7 +332,7 @@ public class InventoryUtils { continue; } // If this isn't the item we're looking for - if (!geyserItem.asItem().javaIdentifier().equals(itemName)) { + if (!geyserItem.asItem().equals(item)) { continue; } @@ -342,7 +348,7 @@ public class InventoryUtils { continue; } // If this isn't the item we're looking for - if (!geyserItem.asItem().javaIdentifier().equals(itemName)) { + if (!geyserItem.asItem().equals(item)) { continue; } @@ -355,17 +361,13 @@ public class InventoryUtils { if (session.getGameMode() == GameMode.CREATIVE) { int slot = findEmptyHotbarSlot(inventory); - ItemMapping mapping = session.getItemMappings().getMapping(itemName); // TODO - if (mapping != null) { - ServerboundSetCreativeModeSlotPacket actionPacket = new ServerboundSetCreativeModeSlotPacket((short)slot, - new ItemStack(mapping.getJavaItem().javaId())); - if ((slot - 36) != inventory.getHeldItemSlot()) { - setHotbarItem(session, slot); - } - session.sendDownstreamGamePacket(actionPacket); - } else { - session.getGeyser().getLogger().debug("Cannot find item for block " + itemName); + ItemMapping mapping = session.getItemMappings().getMapping(item); + ServerboundSetCreativeModeSlotPacket actionPacket = new ServerboundSetCreativeModeSlotPacket((short)slot, + new ItemStack(mapping.getJavaItem().javaId())); + if ((slot - 36) != inventory.getHeldItemSlot()) { + setHotbarItem(session, slot); } + session.sendDownstreamGamePacket(actionPacket); } } 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 8f9be0b98..7e1227f6c 100644 --- a/core/src/main/java/org/geysermc/geyser/util/StatisticsUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/StatisticsUtils.java @@ -96,7 +96,7 @@ public class StatisticsUtils { if (entry.getKey() instanceof BreakBlockStatistic statistic) { Block block = BlockRegistries.JAVA_BLOCKS_TO_RENAME.get(statistic.getId()); if (block != null) { - String identifier = block.javaIdentifier().replace("minecraft:", "block.minecraft."); + String identifier = "block.minecraft." + block.javaIdentifier().value(); content.add(identifier + ": " + entry.getIntValue()); } } From 1e9dbaf38be7895f0d44f408c56c64ef87ff3947 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sat, 18 May 2024 16:54:42 -0400 Subject: [PATCH 019/233] Here is the Spigot change --- .../platform/spigot/world/GeyserSpigotBlockPlaceListener.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserSpigotBlockPlaceListener.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserSpigotBlockPlaceListener.java index b5f4bd4f9..1cdd77c64 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserSpigotBlockPlaceListener.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserSpigotBlockPlaceListener.java @@ -33,7 +33,6 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockPlaceEvent; import org.geysermc.geyser.GeyserImpl; -import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.platform.spigot.world.manager.GeyserSpigotWorldManager; import org.geysermc.geyser.registry.BlockRegistries; @@ -65,6 +64,6 @@ public class GeyserSpigotBlockPlaceListener implements Listener { placeBlockSoundPacket.setIdentifier(":"); session.sendUpstreamPacket(placeBlockSoundPacket); session.setLastBlockPlacePosition(null); - session.setLastBlockPlacedId(null); + session.setLastBlockPlaced(null); } } From d85549c38dd404ade6aa364990c53548f8f4fea3 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sun, 19 May 2024 20:24:19 -0400 Subject: [PATCH 020/233] BlockMapping is removed --- .../java/org/geysermc/geyser/GeyserImpl.java | 11 - .../geyser/entity/type/ItemEntity.java | 3 +- .../type/living/merchant/VillagerEntity.java | 39 ++-- .../entity/type/player/SkullPlayerEntity.java | 26 ++- .../geysermc/geyser/inventory/Container.java | 5 +- .../geyser/inventory/Generic3X3Container.java | 8 +- .../holder/BlockInventoryHolder.java | 2 +- .../geysermc/geyser/level/WorldManager.java | 6 +- .../geyser/level/block/BlockStateValues.java | 220 ++---------------- .../geysermc/geyser/level/block/Blocks.java | 82 +++---- .../geyser/level/block/DoubleChestValue.java | 40 ---- .../geyser/level/block/type/Block.java | 37 ++- .../geyser/level/block/type/BlockState.java | 10 +- .../level/block/type/FlowerPotBlock.java | 16 +- .../geyser/level/block/type/SkullBlock.java | 46 +++- .../block/type/WallSkullBlock.java} | 34 +-- .../geyser/registry/BlockRegistries.java | 15 +- .../populator/BlockRegistryPopulator.java | 176 ++++++-------- .../geyser/registry/type/BlockMappings.java | 3 +- .../geyser/session/cache/SkullCache.java | 27 ++- .../chest/DoubleChestInventoryTranslator.java | 28 +-- .../entity/SkullBlockEntityTranslator.java | 15 +- .../BedrockBlockPickRequestTranslator.java | 16 +- ...BedrockInventoryTransactionTranslator.java | 23 +- .../player/BedrockActionTranslator.java | 28 +-- .../BedrockLevelSoundEventTranslator.java | 15 +- .../level/JavaBlockEntityDataTranslator.java | 2 +- .../java/level/JavaBlockUpdateTranslator.java | 10 +- .../JavaLevelChunkWithLightTranslator.java | 5 +- .../geysermc/geyser/util/StatisticsUtils.java | 2 +- .../util/collection/FixedInt2BooleanMap.java | 120 ---------- .../util/collection/FixedInt2ByteMap.java | 121 ---------- .../util/collection/FixedInt2IntMap.java | 120 ---------- .../util/collection/LecternHasBookMap.java | 75 ------ .../geyser/util/collection/package-info.java | 34 --- core/src/main/resources/mappings | 2 +- .../collection/GeyserCollectionsTest.java | 181 -------------- 37 files changed, 378 insertions(+), 1225 deletions(-) delete mode 100644 core/src/main/java/org/geysermc/geyser/level/block/DoubleChestValue.java rename core/src/main/java/org/geysermc/geyser/{registry/type/BlockMapping.java => level/block/type/WallSkullBlock.java} (58%) delete mode 100644 core/src/main/java/org/geysermc/geyser/util/collection/FixedInt2BooleanMap.java delete mode 100644 core/src/main/java/org/geysermc/geyser/util/collection/FixedInt2ByteMap.java delete mode 100644 core/src/main/java/org/geysermc/geyser/util/collection/FixedInt2IntMap.java delete mode 100644 core/src/main/java/org/geysermc/geyser/util/collection/LecternHasBookMap.java delete mode 100644 core/src/main/java/org/geysermc/geyser/util/collection/package-info.java delete mode 100644 core/src/test/java/org/geysermc/geyser/util/collection/GeyserCollectionsTest.java diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 7be1fe15b..a60a14ea0 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -256,17 +256,6 @@ public class GeyserImpl implements GeyserApi { } VersionCheckUtils.checkForOutdatedJava(logger); - - for (int i = 0; i < BlockRegistries.JAVA_BLOCKS.get().length; i++) { - String oldIdentifier = BlockRegistries.JAVA_BLOCKS.get(i).getJavaIdentifier(); - String newIdentifier = BlockRegistries.BLOCK_STATES.get(i).toString(); - if (!oldIdentifier.equals(newIdentifier)) { - System.out.println("Check block " + oldIdentifier + " " + newIdentifier); - break; - } - } - System.out.println(BlockRegistries.JAVA_BLOCKS.get().length); - System.out.println(BlockRegistries.BLOCK_STATES.get().size()); } private void startInstance() { 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 ead717b34..49eb9ddc4 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 @@ -34,6 +34,7 @@ import org.cloudburstmc.protocol.bedrock.packet.AddItemEntityPacket; import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; @@ -137,7 +138,7 @@ public class ItemEntity extends ThrowableEntity { protected float getDrag() { if (isOnGround()) { Vector3i groundBlockPos = position.toInt().down(1); - int blockState = session.getGeyser().getWorldManager().getBlockAt(session, groundBlockPos); + BlockState blockState = session.getGeyser().getWorldManager().blockAt(session, groundBlockPos); return BlockStateValues.getSlipperiness(blockState) * 0.98f; } return 0.98f; 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 3c2160a2b..fb07572e6 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 @@ -33,8 +33,8 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.packet.MoveEntityAbsolutePacket; import org.geysermc.geyser.entity.EntityDefinition; -import org.geysermc.geyser.registry.BlockRegistries; -import org.geysermc.geyser.registry.type.BlockMapping; +import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.geyser.level.block.type.BlockState; 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; @@ -119,28 +119,29 @@ public class VillagerEntity extends AbstractMerchantEntity { } // The bed block - int blockId = session.getGeyser().getWorldManager().getBlockAt(session, bedPosition); - String fullIdentifier = BlockRegistries.JAVA_BLOCKS.getOrDefault(blockId, BlockMapping.DEFAULT).getJavaIdentifier(); + BlockState state = session.getGeyser().getWorldManager().blockAt(session, bedPosition); // Set the correct position offset and rotation when sleeping int bedRotation = 0; float xOffset = 0; float zOffset = 0; - if (fullIdentifier.contains("facing=south")) { - // bed is facing south - bedRotation = 180; - zOffset = -.5f; - } else if (fullIdentifier.contains("facing=east")) { - // bed is facing east - bedRotation = 90; - xOffset = -.5f; - } else if (fullIdentifier.contains("facing=west")) { - // bed is facing west - bedRotation = 270; - xOffset = .5f; - } else if (fullIdentifier.contains("facing=north")) { - // rotation does not change because north is 0 - zOffset = .5f; + switch (state.getValue(Properties.HORIZONTAL_FACING)) { + case SOUTH -> { + bedRotation = 180; + zOffset = -.5f; + } + case EAST -> { + bedRotation = 90; + xOffset = -.5f; + } + case WEST -> { + bedRotation = 270; + xOffset = .5f; + } + case NORTH -> { + // rotation does not change because north is 0 + zOffset = .5f; + } } setYaw(yaw); 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 89f9c37d6..f2f93b266 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 @@ -34,7 +34,10 @@ 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 org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.geyser.level.block.type.BlockState; +import org.geysermc.geyser.level.block.type.WallSkullBlock; +import org.geysermc.geyser.level.physics.Direction; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.SkullCache; import org.geysermc.geyser.skin.SkullSkinManager; @@ -137,20 +140,19 @@ public class SkullPlayerEntity extends PlayerEntity { float z = skull.getPosition().getZ() + .5f; float rotation; - int blockState = skull.getBlockState(); - byte floorRotation = BlockStateValues.getSkullRotation(blockState); - if (floorRotation == -1) { - // Wall skull + BlockState blockState = skull.getBlockState(); + if (blockState.block() instanceof WallSkullBlock) { y += 0.25f; - rotation = BlockStateValues.getSkullWallDirections().get(blockState); - switch ((int) rotation) { - case 180 -> z += 0.24f; // North - case 0 -> z -= 0.24f; // South - case 90 -> x += 0.24f; // West - case 270 -> x -= 0.24f; // East + Direction direction = blockState.getValue(Properties.HORIZONTAL_FACING); + rotation = WallSkullBlock.getDegrees(direction); + switch (direction) { + case NORTH -> z += 0.24f; + case SOUTH -> z -= 0.24f; + case WEST -> x += 0.24f; + case EAST -> x -= 0.24f; } } else { - rotation = (180f + (floorRotation * 22.5f)) % 360; + rotation = (180f + (blockState.getValue(Properties.ROTATION_16) * 22.5f)) % 360; } moveAbsolute(Vector3f.from(x, y, z), rotation, 0, rotation, true, true); 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 209aeb24f..81818613f 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/Container.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/Container.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.inventory; +import org.geysermc.geyser.level.block.type.Block; import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; import lombok.Getter; import org.checkerframework.checker.nullness.qual.NonNull; @@ -83,9 +84,9 @@ public class Container extends Inventory { * Will be overwritten for droppers. * * @param usingRealBlock whether this container is using a real container or not - * @param javaBlockId the Java block string of the block, if real + * @param block the Java block, if real */ - public void setUsingRealBlock(boolean usingRealBlock, String javaBlockId) { + public void setUsingRealBlock(boolean usingRealBlock, Block block) { isUsingRealBlock = usingRealBlock; } } 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 65e47d877..0b14d1105 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/Generic3X3Container.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/Generic3X3Container.java @@ -26,6 +26,8 @@ package org.geysermc.geyser.inventory; import lombok.Getter; +import org.geysermc.geyser.level.block.Blocks; +import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.inventory.Generic3X3InventoryTranslator; import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; @@ -44,10 +46,10 @@ public class Generic3X3Container extends Container { } @Override - public void setUsingRealBlock(boolean usingRealBlock, String javaBlockId) { - super.setUsingRealBlock(usingRealBlock, javaBlockId); + public void setUsingRealBlock(boolean usingRealBlock, Block block) { + super.setUsingRealBlock(usingRealBlock, block); if (usingRealBlock) { - isDropper = javaBlockId.startsWith("minecraft:dropper"); + isDropper = block == Blocks.DROPPER; } } } 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 686fe39ad..0a51d43ef 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 @@ -90,7 +90,7 @@ public class BlockInventoryHolder extends InventoryHolder { if (isValidBlock(javaBlockString)) { // We can safely use this block inventory.setHolderPosition(session.getLastInteractionBlockPosition()); - ((Container) inventory).setUsingRealBlock(true, javaBlockString[0]); + ((Container) inventory).setUsingRealBlock(true, state.block()); setCustomName(session, session.getLastInteractionBlockPosition(), inventory, state); return true; 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 5edce21dc..6cd9c3e26 100644 --- a/core/src/main/java/org/geysermc/geyser/level/WorldManager.java +++ b/core/src/main/java/org/geysermc/geyser/level/WorldManager.java @@ -59,10 +59,12 @@ import java.util.function.Function; */ public abstract class WorldManager { - public final BlockState blockAt(GeyserSession session, Vector3i vector3i) { - return BlockState.of(this.getBlockAt(session, vector3i)); + @NonNull + public final BlockState blockAt(GeyserSession session, Vector3i vector) { + return this.blockAt(session, vector.getX(), vector.getY(), vector.getZ()); } + @NonNull public BlockState blockAt(GeyserSession session, int x, int y, int z) { return BlockState.of(this.getBlockAt(session, x, y, z)); } 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 9b390f6ee..8bc9cf1e2 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 @@ -25,7 +25,6 @@ package org.geysermc.geyser.level.block; -import com.fasterxml.jackson.databind.JsonNode; import it.unimi.dsi.fastutil.ints.*; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; @@ -36,10 +35,6 @@ import org.geysermc.geyser.level.block.type.PistonBlock; import org.geysermc.geyser.level.physics.Direction; import org.geysermc.geyser.level.physics.PistonBehavior; import org.geysermc.geyser.registry.BlockRegistries; -import org.geysermc.geyser.registry.type.BlockMapping; -import org.geysermc.geyser.util.collection.FixedInt2ByteMap; -import org.geysermc.geyser.util.collection.FixedInt2IntMap; -import org.geysermc.geyser.util.collection.LecternHasBookMap; import java.util.Locale; @@ -47,35 +42,13 @@ import java.util.Locale; * Used for block entities if the Java block state contains Bedrock block information. */ public final class BlockStateValues { - private static final IntSet ALL_CAULDRONS = 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 Int2ObjectMap DOUBLE_CHEST_VALUES = new Int2ObjectOpenHashMap<>(); - private static final Int2ObjectMap FLOWER_POT_VALUES = new Int2ObjectOpenHashMap<>(); private static final IntSet HORIZONTAL_FACING_JIGSAWS = new IntOpenHashSet(); - private static final LecternHasBookMap LECTERN_BOOK_STATES = new LecternHasBookMap(); - private static final IntSet NON_WATER_CAULDRONS = new IntOpenHashSet(); - private static final Int2IntMap NOTEBLOCK_PITCHES = new FixedInt2IntMap(); - private static final Int2BooleanMap PISTON_VALUES = new Int2BooleanOpenHashMap(); private static final IntSet STICKY_PISTONS = new IntOpenHashSet(); private static final Object2IntMap PISTON_HEADS = new Object2IntOpenHashMap<>(); private static final Int2ObjectMap PISTON_ORIENTATION = new Int2ObjectOpenHashMap<>(); 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(); private static final Int2IntMap WATER_LEVEL = new Int2IntOpenHashMap(); - private static final IntSet UPPER_DOORS = new IntOpenHashSet(); - public static int JAVA_FURNACE_ID; - public static int JAVA_FURNACE_LIT_ID; - public static int JAVA_HONEY_BLOCK_ID; - public static int JAVA_SLIME_BLOCK_ID; - public static int JAVA_SPAWNER_ID; public static int JAVA_WATER_ID; public static final int NUM_WATER_LEVELS = 9; @@ -85,66 +58,9 @@ public final class BlockStateValues { * * @param javaId The Java Identifier of the block * @param javaBlockState the Java Block State of the block - * @param blockData JsonNode of info about the block from blocks.json */ - public static void storeBlockStateValues(String javaId, int javaBlockState, JsonNode blockData) { - JsonNode bannerColor = blockData.get("banner_color"); - if (bannerColor != null) { - BANNER_COLORS.put(javaBlockState, (byte) bannerColor.intValue()); - return; // There will never be a banner color and a skull variant - } - - JsonNode bedColor = blockData.get("bed_color"); - if (bedColor != null) { - BED_COLORS.put(javaBlockState, (byte) bedColor.intValue()); - 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 (blockData.get("double_chest_position") != null) { - boolean isX = (blockData.get("x") != null); - boolean isDirectionPositive = ((blockData.get("x") != null && blockData.get("x").asBoolean()) || - (blockData.get("z") != null && blockData.get("z").asBoolean())); - boolean isLeft = (blockData.get("double_chest_position").asText().contains("left")); - DOUBLE_CHEST_VALUES.put(javaBlockState, new DoubleChestValue(isX, isDirectionPositive, isLeft)); - return; - } - - if (javaId.startsWith("minecraft:potted_") || javaId.equals("minecraft:flower_pot")) { - String name = javaId.replace("potted_", ""); - if (name.contains("azalea")) { - // Exception to the rule - name = name.replace("_bush", ""); - } - FLOWER_POT_VALUES.put(javaBlockState, name); - return; - } - - if (javaId.startsWith("minecraft:lectern")) { - LECTERN_BOOK_STATES.put(javaBlockState, javaId.contains("has_book=true")); - return; - } - - JsonNode notePitch = blockData.get("note_pitch"); - if (notePitch != null) { - NOTEBLOCK_PITCHES.put(javaBlockState, blockData.get("note_pitch").intValue()); - return; - } - + public static void storeBlockStateValues(String javaId, int javaBlockState) { if (javaId.contains("piston[")) { // minecraft:moving_piston, minecraft:sticky_piston, minecraft:piston - if (javaId.startsWith("minecraft:moving_piston")) { - MOVING_PISTONS.add(javaBlockState); - } else { - PISTON_VALUES.put(javaBlockState, javaId.contains("extended=true")); - } if (javaId.contains("sticky")) { STICKY_PISTONS.add(javaBlockState); } @@ -158,40 +74,6 @@ public final class BlockStateValues { return; } - JsonNode skullVariation = blockData.get("variation"); - if (skullVariation != null) { - SKULL_VARIANTS.put(javaBlockState, (byte) skullVariation.intValue()); - } - - JsonNode skullRotation = blockData.get("skull_rotation"); - if (skullRotation != null) { - 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) { - case "north" -> 180; - case "west" -> 90; - case "east" -> 270; - default -> 0; // Also south - }; - SKULL_WALL_DIRECTIONS.put(javaBlockState, rotation); - } - - JsonNode shulkerDirection = blockData.get("shulker_direction"); - if (shulkerDirection != null) { - BlockStateValues.SHULKERBOX_DIRECTIONS.put(javaBlockState, (byte) shulkerDirection.intValue()); - return; - } - if (javaId.startsWith("minecraft:water") && !javaId.contains("cauldron")) { String strLevel = javaId.substring(javaId.lastIndexOf("level=") + 6, javaId.length() - 1); int level = Integer.parseInt(strLevel); @@ -205,48 +87,7 @@ public final class BlockStateValues { if (direction.isHorizontal()) { HORIZONTAL_FACING_JIGSAWS.add(javaBlockState); } - return; } - - if (javaId.contains("cauldron")) { - ALL_CAULDRONS.add(javaBlockState); - } - if (javaId.contains("_cauldron") && !javaId.contains("water_")) { - NON_WATER_CAULDRONS.add(javaBlockState); - } - - if (javaId.contains("_door[") && javaId.contains("half=upper")) { - UPPER_DOORS.add(javaBlockState); - } - } - - /** - * 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. - * - * @param state BlockState of the block - * @return Banner color integer or -1 if no color - */ - public static int getBannerColor(int state) { - return BANNER_COLORS.getOrDefault(state, -1); - } - - /** - * @return if this Java block state is a non-empty non-water cauldron - */ - public static boolean isNonWaterCauldron(int state) { - return NON_WATER_CAULDRONS.contains(state); - } - - /** - * 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 - */ - public static boolean isCauldron(int state) { - return ALL_CAULDRONS.contains(state); } /** @@ -256,13 +97,6 @@ public final class BlockStateValues { return HORIZONTAL_FACING_JIGSAWS; } - /** - * @return the lectern book state map pointing to book present state - */ - public static LecternHasBookMap getLecternBookStates() { - return LECTERN_BOOK_STATES; - } - public static boolean isStickyPiston(int blockState) { return STICKY_PISTONS.contains(blockState); } @@ -354,38 +188,6 @@ public final class BlockStateValues { }; } - /** - * Skull variations are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock. - * This gives a byte variant ID that Bedrock can use. - * - * @param state BlockState of the block - * @return Skull variant byte or -1 if no variant - */ - public static byte getSkullVariant(int state) { - return SKULL_VARIANTS.getOrDefault(state, (byte) -1); - } - - /** - * Skull rotations are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock. - * This gives a byte rotation that Bedrock can use. - * - * @param state BlockState of the block - * @return Skull rotation value or -1 if no value - */ - public static byte getSkullRotation(int state) { - return SKULL_ROTATIONS.getOrDefault(state, (byte) -1); - } - - /** - * 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. - * - * @return Skull wall rotation value with the blockstate - */ - public static Int2IntMap getSkullWallDirections() { - return SKULL_WALL_DIRECTIONS; - } - /** * Get the level of water from the block state. * @@ -427,14 +229,18 @@ public final class BlockStateValues { * @param state BlockState of the block * @return The block's slipperiness */ - public static float getSlipperiness(int state) { - 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; - case "minecraft:blue_ice" -> 0.989f; - default -> 0.6f; - }; + public static float getSlipperiness(BlockState state) { + Block block = state.block(); + if (block == Blocks.SLIME_BLOCK) { + return 0.8f; + } + if (block == Blocks.ICE || block == Blocks.PACKED_ICE) { + return 0.98f; + } + if (block == Blocks.BLUE_ICE) { + return 0.989f; + } + return 0.6f; } private static Direction getBlockDirection(String javaId) { diff --git a/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java index 485d52161..178887754 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.level.block; +import org.geysermc.geyser.item.Items; import org.geysermc.geyser.level.block.property.ChestType; import org.geysermc.geyser.level.block.type.*; import org.geysermc.geyser.level.physics.Axis; @@ -308,7 +309,7 @@ public final class Blocks { public static final Block FERN = register(new Block("fern", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block DEAD_BUSH = register(new Block("dead_bush", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block SEAGRASS = register(new Block("seagrass", builder().pushReaction(PistonBehavior.DESTROY))); - public static final Block TALL_SEAGRASS = register(new Block("tall_seagrass", builder().pushReaction(PistonBehavior.DESTROY) + public static final Block TALL_SEAGRASS = register(new Block("tall_seagrass", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.SEAGRASS) .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); public static final Block PISTON = register(new PistonBlock("piston", builder().destroyTime(1.5f).pushReaction(PistonBehavior.BLOCK) .booleanState(EXTENDED) @@ -758,9 +759,9 @@ public final class Blocks { .booleanState(WEST))); public static final Block PUMPKIN = register(new Block("pumpkin", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY))); public static final Block MELON = register(new Block("melon", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY))); - public static final Block ATTACHED_PUMPKIN_STEM = register(new Block("attached_pumpkin_stem", builder().pushReaction(PistonBehavior.DESTROY) + public static final Block ATTACHED_PUMPKIN_STEM = register(new Block("attached_pumpkin_stem", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.PUMPKIN_SEEDS) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block ATTACHED_MELON_STEM = register(new Block("attached_melon_stem", builder().pushReaction(PistonBehavior.DESTROY) + public static final Block ATTACHED_MELON_STEM = register(new Block("attached_melon_stem", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.MELON_SEEDS) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); public static final Block PUMPKIN_STEM = register(new Block("pumpkin_stem", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_7, 0, 7))); @@ -963,46 +964,46 @@ public final class Blocks { .enumState(ATTACH_FACE, "floor", "wall", "ceiling") .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block SKELETON_SKULL = register(new SkullBlock("skeleton_skull", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block SKELETON_SKULL = register(new SkullBlock("skeleton_skull", SkullBlock.Type.SKELETON, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) .intState(ROTATION_16, 0, 15))); - public static final Block SKELETON_WALL_SKULL = register(new SkullBlock("skeleton_wall_skull", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block SKELETON_WALL_SKULL = register(new WallSkullBlock("skeleton_wall_skull", SkullBlock.Type.SKELETON, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block WITHER_SKELETON_SKULL = register(new SkullBlock("wither_skeleton_skull", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block WITHER_SKELETON_SKULL = register(new SkullBlock("wither_skeleton_skull", SkullBlock.Type.WITHER_SKELETON, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) .intState(ROTATION_16, 0, 15))); - public static final Block WITHER_SKELETON_WALL_SKULL = register(new SkullBlock("wither_skeleton_wall_skull", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block WITHER_SKELETON_WALL_SKULL = register(new WallSkullBlock("wither_skeleton_wall_skull", SkullBlock.Type.WITHER_SKELETON, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block ZOMBIE_HEAD = register(new SkullBlock("zombie_head", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block ZOMBIE_HEAD = register(new SkullBlock("zombie_head", SkullBlock.Type.ZOMBIE, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) .intState(ROTATION_16, 0, 15))); - public static final Block ZOMBIE_WALL_HEAD = register(new SkullBlock("zombie_wall_head", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block ZOMBIE_WALL_HEAD = register(new WallSkullBlock("zombie_wall_head", SkullBlock.Type.ZOMBIE, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block PLAYER_HEAD = register(new SkullBlock("player_head", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block PLAYER_HEAD = register(new SkullBlock("player_head", SkullBlock.Type.PLAYER, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) .intState(ROTATION_16, 0, 15))); - public static final Block PLAYER_WALL_HEAD = register(new SkullBlock("player_wall_head", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block PLAYER_WALL_HEAD = register(new WallSkullBlock("player_wall_head", SkullBlock.Type.PLAYER, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block CREEPER_HEAD = register(new SkullBlock("creeper_head", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block CREEPER_HEAD = register(new SkullBlock("creeper_head", SkullBlock.Type.CREEPER, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) .intState(ROTATION_16, 0, 15))); - public static final Block CREEPER_WALL_HEAD = register(new SkullBlock("creeper_wall_head", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block CREEPER_WALL_HEAD = register(new WallSkullBlock("creeper_wall_head", SkullBlock.Type.CREEPER, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block DRAGON_HEAD = register(new SkullBlock("dragon_head", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block DRAGON_HEAD = register(new SkullBlock("dragon_head", SkullBlock.Type.DRAGON, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) .intState(ROTATION_16, 0, 15))); - public static final Block DRAGON_WALL_HEAD = register(new SkullBlock("dragon_wall_head", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block DRAGON_WALL_HEAD = register(new WallSkullBlock("dragon_wall_head", SkullBlock.Type.DRAGON, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block PIGLIN_HEAD = register(new SkullBlock("piglin_head", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block PIGLIN_HEAD = register(new SkullBlock("piglin_head", SkullBlock.Type.PIGLIN, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) .intState(ROTATION_16, 0, 15))); - public static final Block PIGLIN_WALL_HEAD = register(new SkullBlock("piglin_wall_head", builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block PIGLIN_WALL_HEAD = register(new WallSkullBlock("piglin_wall_head", SkullBlock.Type.PIGLIN, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); public static final Block ANVIL = register(new Block("anvil", builder().requiresCorrectToolForDrops().destroyTime(5.0f).pushReaction(PistonBehavior.BLOCK) @@ -1694,7 +1695,7 @@ public final class Blocks { public static final Block BLACK_CONCRETE_POWDER = register(new Block("black_concrete_powder", builder().destroyTime(0.5f))); public static final Block KELP = register(new Block("kelp", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_25, 0, 25))); - public static final Block KELP_PLANT = register(new Block("kelp_plant", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block KELP_PLANT = register(new Block("kelp_plant", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.KELP))); public static final Block DRIED_KELP_BLOCK = register(new Block("dried_kelp_block", builder().destroyTime(0.5f))); public static final Block TURTLE_EGG = register(new Block("turtle_egg", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .intState(EGGS, 1, 4) @@ -1787,7 +1788,7 @@ public final class Blocks { public static final Block BLUE_ICE = register(new Block("blue_ice", builder().destroyTime(2.8f))); public static final Block CONDUIT = register(new Block("conduit", builder().setBlockEntity().destroyTime(3.0f) .booleanState(WATERLOGGED))); - public static final Block BAMBOO_SAPLING = register(new Block("bamboo_sapling", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY))); + public static final Block BAMBOO_SAPLING = register(new Block("bamboo_sapling", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.BAMBOO))); public static final Block BAMBOO = register(new Block("bamboo", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .intState(AGE_1, 0, 1) .enumState(BAMBOO_LEAVES, "none", "small", "large") @@ -2072,10 +2073,10 @@ public final class Blocks { public static final Block SHROOMLIGHT = register(new Block("shroomlight", builder().destroyTime(1.0f))); public static final Block WEEPING_VINES = register(new Block("weeping_vines", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_25, 0, 25))); - public static final Block WEEPING_VINES_PLANT = register(new Block("weeping_vines_plant", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block WEEPING_VINES_PLANT = register(new Block("weeping_vines_plant", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.WEEPING_VINES))); public static final Block TWISTING_VINES = register(new Block("twisting_vines", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_25, 0, 25))); - public static final Block TWISTING_VINES_PLANT = register(new Block("twisting_vines_plant", builder().pushReaction(PistonBehavior.DESTROY))); + public static final Block TWISTING_VINES_PLANT = register(new Block("twisting_vines_plant", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.TWISTING_VINES))); public static final Block CRIMSON_ROOTS = register(new Block("crimson_roots", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block CRIMSON_PLANKS = register(new Block("crimson_planks", builder().destroyTime(2.0f))); public static final Block WARPED_PLANKS = register(new Block("warped_planks", builder().destroyTime(2.0f))); @@ -2319,39 +2320,39 @@ public final class Blocks { .intState(CANDLES, 1, 4) .booleanState(LIT) .booleanState(WATERLOGGED))); - public static final Block CANDLE_CAKE = register(new Block("candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block CANDLE_CAKE = register(new Block("candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE) .booleanState(LIT))); - public static final Block WHITE_CANDLE_CAKE = register(new Block("white_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block WHITE_CANDLE_CAKE = register(new Block("white_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE) .booleanState(LIT))); - public static final Block ORANGE_CANDLE_CAKE = register(new Block("orange_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block ORANGE_CANDLE_CAKE = register(new Block("orange_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE) .booleanState(LIT))); - public static final Block MAGENTA_CANDLE_CAKE = register(new Block("magenta_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block MAGENTA_CANDLE_CAKE = register(new Block("magenta_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE) .booleanState(LIT))); - public static final Block LIGHT_BLUE_CANDLE_CAKE = register(new Block("light_blue_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block LIGHT_BLUE_CANDLE_CAKE = register(new Block("light_blue_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE) .booleanState(LIT))); - public static final Block YELLOW_CANDLE_CAKE = register(new Block("yellow_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block YELLOW_CANDLE_CAKE = register(new Block("yellow_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE) .booleanState(LIT))); - public static final Block LIME_CANDLE_CAKE = register(new Block("lime_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block LIME_CANDLE_CAKE = register(new Block("lime_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE) .booleanState(LIT))); - public static final Block PINK_CANDLE_CAKE = register(new Block("pink_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block PINK_CANDLE_CAKE = register(new Block("pink_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE) .booleanState(LIT))); - public static final Block GRAY_CANDLE_CAKE = register(new Block("gray_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block GRAY_CANDLE_CAKE = register(new Block("gray_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE) .booleanState(LIT))); - public static final Block LIGHT_GRAY_CANDLE_CAKE = register(new Block("light_gray_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block LIGHT_GRAY_CANDLE_CAKE = register(new Block("light_gray_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE) .booleanState(LIT))); - public static final Block CYAN_CANDLE_CAKE = register(new Block("cyan_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block CYAN_CANDLE_CAKE = register(new Block("cyan_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE) .booleanState(LIT))); - public static final Block PURPLE_CANDLE_CAKE = register(new Block("purple_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block PURPLE_CANDLE_CAKE = register(new Block("purple_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE) .booleanState(LIT))); - public static final Block BLUE_CANDLE_CAKE = register(new Block("blue_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block BLUE_CANDLE_CAKE = register(new Block("blue_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE) .booleanState(LIT))); - public static final Block BROWN_CANDLE_CAKE = register(new Block("brown_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block BROWN_CANDLE_CAKE = register(new Block("brown_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE) .booleanState(LIT))); - public static final Block GREEN_CANDLE_CAKE = register(new Block("green_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block GREEN_CANDLE_CAKE = register(new Block("green_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE) .booleanState(LIT))); - public static final Block RED_CANDLE_CAKE = register(new Block("red_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block RED_CANDLE_CAKE = register(new Block("red_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE) .booleanState(LIT))); - public static final Block BLACK_CANDLE_CAKE = register(new Block("black_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) + public static final Block BLACK_CANDLE_CAKE = register(new Block("black_candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE) .booleanState(LIT))); public static final Block AMETHYST_BLOCK = register(new Block("amethyst_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); public static final Block BUDDING_AMETHYST = register(new Block("budding_amethyst", builder().requiresCorrectToolForDrops().destroyTime(1.5f).pushReaction(PistonBehavior.DESTROY))); @@ -2682,7 +2683,7 @@ public final class Blocks { public static final Block CAVE_VINES = register(new Block("cave_vines", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_25, 0, 25) .booleanState(BERRIES))); - public static final Block CAVE_VINES_PLANT = register(new Block("cave_vines_plant", builder().pushReaction(PistonBehavior.DESTROY) + public static final Block CAVE_VINES_PLANT = register(new Block("cave_vines_plant", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.GLOW_BERRIES) .booleanState(BERRIES))); public static final Block SPORE_BLOSSOM = register(new Block("spore_blossom", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block AZALEA = register(new Block("azalea", builder().pushReaction(PistonBehavior.DESTROY))); @@ -2811,7 +2812,8 @@ public final class Blocks { .booleanState(WATERLOGGED))); private static T register(T block) { - BlockRegistries.JAVA_BLOCKS_TO_RENAME.get().add(block); + block.setJavaId(BlockRegistries.JAVA_BLOCKS.get().size()); + BlockRegistries.JAVA_BLOCKS.get().add(block); return block; } 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 deleted file mode 100644 index 97c861df7..000000000 --- a/core/src/main/java/org/geysermc/geyser/level/block/DoubleChestValue.java +++ /dev/null @@ -1,40 +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.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( - boolean isFacingEast, - boolean isDirectionPositive, - boolean isLeft) { - -} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java b/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java index 491894a35..b31c9aeb5 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java @@ -37,24 +37,33 @@ import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.level.block.Blocks; -import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.level.block.property.Property; import org.geysermc.geyser.level.physics.PistonBehavior; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.intellij.lang.annotations.Subst; import java.util.*; +import java.util.function.Supplier; import java.util.stream.Stream; public class Block { public static final int JAVA_AIR_ID = 0; private final Key javaIdentifier; + /** + * Can you harvest this with your hand. + */ private final boolean requiresCorrectToolForDrops; private final boolean hasBlockEntity; private final float destroyTime; private final @NonNull PistonBehavior pushReaction; + /** + * Used for classes we don't have implemented yet that override Mojmap getCloneItemStack with their own item. + * A supplier prevents any issues arising where the Items class finishes before the Blocks class. + */ + private final Supplier pickItem; protected Item item = null; private int javaId = -1; @@ -64,10 +73,13 @@ public class Block { this.hasBlockEntity = builder.hasBlockEntity; this.destroyTime = builder.destroyTime; this.pushReaction = builder.pushReaction; + this.pickItem = builder.pickItem; processStates(builder.build(this)); } public void updateBlock(GeyserSession session, BlockState state, Vector3i position) { + checkForEmptySkull(session, state, position); + BlockDefinition definition = session.getBlockMappings().getBedrockBlock(state); sendBlockUpdatePacket(session, state, definition, position); @@ -118,8 +130,7 @@ public class Block { UpdateBlockPacket waterPacket = new UpdateBlockPacket(); waterPacket.setDataLayer(1); waterPacket.setBlockPosition(position); - Boolean waterlogged = state.getValue(Properties.WATERLOGGED); - if (waterlogged == Boolean.TRUE) { + if (BlockRegistries.WATERLOGGED.get().get(state.javaId())) { waterPacket.setDefinition(session.getBlockMappings().getBedrockWater()); } else { waterPacket.setDefinition(session.getBlockMappings().getBedrockAir()); @@ -127,6 +138,13 @@ public class Block { session.sendUpstreamPacket(waterPacket); } + protected void checkForEmptySkull(GeyserSession session, BlockState state, Vector3i position) { + if (!(state.block() instanceof SkullBlock)) { + // Skull is gone + session.getSkullCache().removeSkull(position); + } + } + protected void handleLecternBlockUpdate(GeyserSession session, BlockState state, Vector3i position) { // Block state is out of bounds of this map - lectern has been destroyed, if it existed if (!session.getGeyser().getWorldManager().shouldExpectLecternHandled(session)) { @@ -141,6 +159,13 @@ public class Block { return this.item; } + public ItemStack pickItem(BlockState state) { + if (this.pickItem != null) { + return new ItemStack(this.pickItem.get().javaId()); + } + return new ItemStack(this.asItem().javaId()); + } + /** * A list of BlockStates is created pertaining to this block. Do we need any of them? If so, override this method. */ @@ -198,6 +223,7 @@ public class Block { private boolean hasBlockEntity = false; private PistonBehavior pushReaction = PistonBehavior.NORMAL; private float destroyTime; + private Supplier pickItem; /** * For states that we're just tracking for mirroring Java states. @@ -248,6 +274,11 @@ public class Block { return this; } + public Builder pickItem(Supplier pickItem) { + this.pickItem = pickItem; + return this; + } + private List build(Block block) { if (states.isEmpty()) { BlockState state = new BlockState(block, BlockRegistries.BLOCK_STATES.get().size()); diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java index cb375eaf9..4fed30e7a 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java @@ -37,7 +37,7 @@ public final class BlockState { private final int javaId; private final Reference2ObjectMap, Comparable> states; - BlockState(Block block, int javaId) { + public BlockState(Block block, int javaId) { this(block, javaId, Reference2ObjectMaps.emptyMap()); } @@ -52,6 +52,14 @@ public final class BlockState { return (T) states.get(property); } + public boolean getValue(Property property, boolean def) { + var value = states.get(property); + if (value == null) { + return def; + } + return (Boolean) value; + } + public Block block() { return block; } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/FlowerPotBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/FlowerPotBlock.java index 53d0b1ec1..5107616af 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/FlowerPotBlock.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/FlowerPotBlock.java @@ -34,6 +34,7 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.level.block.entity.BedrockChunkWantsBlockEntityTag; import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator; import org.geysermc.geyser.util.BlockEntityUtils; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; public class FlowerPotBlock extends Block implements BedrockChunkWantsBlockEntityTag { private final Block flower; @@ -68,11 +69,24 @@ public class FlowerPotBlock extends Block implements BedrockChunkWantsBlockEntit if (this.flower != Blocks.AIR) { // Get the Bedrock CompoundTag of the block. // This is where we need to store the *Java* name because Bedrock has six minecraft:sapling blocks with different block states. - NbtMap plant = session.getBlockMappings().getFlowerPotBlocks().get(this.flower.javaIdentifier().asString()); + // TODO flattening might make this nicer in the future! + NbtMap plant = session.getBlockMappings().getFlowerPotBlocks().get(this.flower); if (plant != null) { tagBuilder.putCompound("PlantBlock", plant.toBuilder().build()); } } return tagBuilder.build(); } + + @Override + public ItemStack pickItem(BlockState state) { + if (this.flower != Blocks.AIR) { + return new ItemStack(this.flower.asItem().javaId()); + } + return super.pickItem(state); + } + + public Block flower() { + return flower; + } } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/SkullBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/SkullBlock.java index 01a757eae..76b532919 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/SkullBlock.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/SkullBlock.java @@ -27,28 +27,58 @@ package org.geysermc.geyser.level.block.type; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; -import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.SkullCache; public class SkullBlock extends Block { - public SkullBlock(String javaIdentifier, Builder builder) { + private final Type type; + + public SkullBlock(String javaIdentifier, Type type, Builder builder) { super(javaIdentifier, builder); + this.type = type; } @Override protected void sendBlockUpdatePacket(GeyserSession session, BlockState state, BlockDefinition definition, Vector3i position) { - int skullVariant = BlockStateValues.getSkullVariant(state.javaId()); // TODO - if (skullVariant == -1) { - // Skull is gone - session.getSkullCache().removeSkull(position); - } else if (skullVariant == 3) { + if (this.type == Type.PLAYER) { // The changed block was a player skull so check if a custom block was defined for this skull - SkullCache.Skull skull = session.getSkullCache().updateSkull(position, state.javaId()); + SkullCache.Skull skull = session.getSkullCache().updateSkull(position, state); if (skull != null && skull.getBlockDefinition() != null) { definition = skull.getBlockDefinition(); } } super.sendBlockUpdatePacket(session, state, definition, position); } + + @Override + protected void checkForEmptySkull(GeyserSession session, BlockState state, Vector3i position) { + // It's not an empty skull. + } + + public Type skullType() { + return type; + } + + /** + * Enum order matches Java. + */ + public enum Type { + SKELETON(0), + WITHER_SKELETON(1), + PLAYER(3), + ZOMBIE(2), + CREEPER(4), + PIGLIN(6), + DRAGON(5); + + private final int bedrockId; + + Type(int bedrockId) { + this.bedrockId = bedrockId; + } + + public int bedrockId() { + return bedrockId; + } + } } diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/BlockMapping.java b/core/src/main/java/org/geysermc/geyser/level/block/type/WallSkullBlock.java similarity index 58% rename from core/src/main/java/org/geysermc/geyser/registry/type/BlockMapping.java rename to core/src/main/java/org/geysermc/geyser/level/block/type/WallSkullBlock.java index 0520924f8..e8fedcc76 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/type/BlockMapping.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/WallSkullBlock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * Copyright (c) 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,21 +23,27 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.geyser.registry.type; +package org.geysermc.geyser.level.block.type; -import lombok.Builder; -import lombok.Value; -import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.geyser.level.physics.Direction; -@Builder -@Value -public class BlockMapping { - public static BlockMapping DEFAULT = BlockMapping.builder().javaIdentifier("minecraft:air").build(); +public class WallSkullBlock extends SkullBlock { + public WallSkullBlock(String javaIdentifier, Type type, Builder builder) { + super(javaIdentifier, type, builder); + } - String javaIdentifier; + public static int getDegrees(BlockState state) { + return getDegrees(state.getValue(Properties.HORIZONTAL_FACING)); + } - @Nullable String pickItem; - - boolean isBlockEntity; - boolean isNonVanilla; + public static int getDegrees(Direction direction) { + return switch (direction) { + case NORTH -> 180; + case WEST -> 90; + case EAST -> 270; + case SOUTH -> 0; + default -> throw new IllegalStateException(); + }; + } } 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 a18ffff7d..93ac5e457 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java +++ b/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java @@ -42,7 +42,6 @@ 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; @@ -67,24 +66,22 @@ public class BlockRegistries { */ public static final ListRegistry BLOCK_STATES = ListRegistry.create(RegistryLoaders.empty(ArrayList::new)); - public static final ListRegistry JAVA_BLOCKS_TO_RENAME = ListRegistry.create(RegistryLoaders.empty(ArrayList::new)); - /** * A mapped registry which stores Java to Bedrock block identifiers. */ public static final SimpleMappedRegistry JAVA_TO_BEDROCK_IDENTIFIERS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new)); - /** - * A registry which stores Java IDs to {@link BlockMapping}, containing miscellaneous information about - * blocks and their behavior in many cases. - */ - 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 ListRegistry COLLISIONS; + /** + * A registry which stores Java IDs to {@link Block}, containing miscellaneous information about + * blocks and their behavior in many cases. + */ + public static final ListRegistry JAVA_BLOCKS = ListRegistry.create(RegistryLoaders.empty(ArrayList::new)); + /** * A mapped registry containing the Java identifiers to IDs. */ 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 0180fc8b7..a0af4cfa0 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 @@ -32,13 +32,12 @@ 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.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.objects.*; import org.cloudburstmc.blockstateupdater.BlockStateUpdater; 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.nbt.*; 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; @@ -50,21 +49,26 @@ 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.item.type.Item; +import org.geysermc.geyser.item.Items; import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.Blocks; +import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.level.block.type.Block; +import org.geysermc.geyser.level.block.type.BlockState; +import org.geysermc.geyser.level.block.type.FlowerPotBlock; import org.geysermc.geyser.level.physics.PistonBehavior; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; -import org.geysermc.geyser.registry.type.BlockMapping; import org.geysermc.geyser.registry.type.BlockMappings; import org.geysermc.geyser.registry.type.GeyserBedrockBlock; import org.geysermc.geyser.util.BlockUtils; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import java.io.DataInputStream; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.*; +import java.util.stream.Stream; import java.util.zip.GZIPInputStream; /** @@ -102,7 +106,7 @@ public final class BlockRegistryPopulator { public static void populate(Stage stage) { switch (stage) { - case PRE_INIT, POST_INIT -> nullifyBlocksNode(); + case PRE_INIT, POST_INIT -> nullifyBlocksNbt(); case INIT_JAVA -> registerJavaBlocks(); case INIT_BEDROCK -> registerBedrockBlocks(); default -> throw new IllegalArgumentException("Unknown stage: " + stage); @@ -110,14 +114,14 @@ public final class BlockRegistryPopulator { } /** - * Stores the raw blocks JSON until it is no longer needed. + * Stores the raw blocks NBT until it is no longer needed. */ - private static JsonNode BLOCKS_JSON; + private static List BLOCKS_NBT; private static int MIN_CUSTOM_RUNTIME_ID = -1; private static int JAVA_BLOCKS_SIZE = -1; - private static void nullifyBlocksNode() { - BLOCKS_JSON = null; + private static void nullifyBlocksNbt() { + BLOCKS_NBT = null; } private static void registerBedrockBlocks() { @@ -218,19 +222,31 @@ public final class BlockRegistryPopulator { int javaRuntimeId = -1; + List javaBlockStates = BlockRegistries.BLOCK_STATES.get(); + GeyserBedrockBlock airDefinition = null; BlockDefinition commandBlockDefinition = null; BlockDefinition mobSpawnerBlockDefinition = null; BlockDefinition waterDefinition = null; BlockDefinition movingBlockDefinition = null; - Iterator> blocksIterator = BLOCKS_JSON.fields(); + Iterator blocksIterator = BLOCKS_NBT.iterator(); Remapper stateMapper = blockMappers.get(palette); GeyserBedrockBlock[] javaToBedrockBlocks = new GeyserBedrockBlock[JAVA_BLOCKS_SIZE]; GeyserBedrockBlock[] javaToVanillaBedrockBlocks = new GeyserBedrockBlock[JAVA_BLOCKS_SIZE]; - Map flowerPotBlocks = new Object2ObjectOpenHashMap<>(); + // Stream isn't ideal. + List javaPottable = BlockRegistries.JAVA_BLOCKS.get() + .parallelStream() + .flatMap(block -> { + if (block instanceof FlowerPotBlock flowerPot && flowerPot.flower() != Blocks.AIR) { + return Stream.of(flowerPot.flower()); + } + return null; + }) + .toList(); + Map flowerPotBlocks = new Object2ObjectOpenHashMap<>(); Map itemFrames = new Object2ObjectOpenHashMap<>(); Set jigsawDefinitions = new ObjectOpenHashSet<>(); @@ -239,10 +255,11 @@ public final class BlockRegistryPopulator { BlockMappings.BlockMappingsBuilder builder = BlockMappings.builder(); while (blocksIterator.hasNext()) { javaRuntimeId++; - Map.Entry entry = blocksIterator.next(); - String javaId = entry.getKey(); + NbtMap entry = blocksIterator.next(); + BlockState blockState = javaBlockStates.get(javaRuntimeId); + String javaId = blockState.toString(); - NbtMap originalBedrockTag = buildBedrockState(entry.getValue()); + NbtMap originalBedrockTag = buildBedrockState(blockState, entry); NbtMap bedrockTag = stateMapper.remap(originalBedrockTag); GeyserBedrockBlock vanillaBedrockDefinition = blockStateOrderedMap.get(bedrockTag); @@ -274,35 +291,27 @@ public final class BlockRegistryPopulator { case "minecraft:moving_piston[facing=north,type=normal]" -> movingBlockDefinition = bedrockDefinition; } - if (javaId.contains("jigsaw")) { + if (blockState.block() == Blocks.JIGSAW) { 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); - } - } + if (blockState.block() == Blocks.STRUCTURE_BLOCK) { + String mode = blockState.getValue(Properties.STRUCTUREBLOCK_MODE); + structureBlockDefinitions.put(mode.toUpperCase(Locale.ROOT), bedrockDefinition); } - boolean waterlogged = entry.getKey().contains("waterlogged=true") - || javaId.contains("minecraft:bubble_column") || javaId.contains("minecraft:kelp") || javaId.contains("seagrass"); + boolean waterlogged = blockState.getValue(Properties.WATERLOGGED, false) + || blockState.block() == Blocks.BUBBLE_COLUMN || blockState.block() == Blocks.KELP || blockState.block() == Blocks.SEAGRASS; if (waterlogged) { int finalJavaRuntimeId = javaRuntimeId; BlockRegistries.WATERLOGGED.register(set -> set.set(finalJavaRuntimeId)); } - String cleanJavaIdentifier = BlockUtils.getCleanIdentifier(entry.getKey()); - // Get the tag needed for non-empty flower pots - if (entry.getValue().get("pottable") != null) { - flowerPotBlocks.put(cleanJavaIdentifier.intern(), blockStates.get(bedrockDefinition.getRuntimeId())); + if (javaPottable.contains(blockState.block())) { + // Specifically NOT putIfAbsent - mangrove propagule breaks otherwise + flowerPotBlocks.put(blockState.block(), blockStates.get(bedrockDefinition.getRuntimeId())); } javaToVanillaBedrockBlocks[javaRuntimeId] = vanillaBedrockDefinition; @@ -386,9 +395,10 @@ public final class BlockRegistryPopulator { } private static void registerJavaBlocks() { - JsonNode blocksJson; - try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow("mappings/blocks.json")) { - blocksJson = GeyserImpl.JSON_MAPPER.readTree(stream); + List blocksNbt; + try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow("mappings/blocks.nbt")) { + blocksNbt = ((NbtMap) NbtUtils.createGZIPReader(stream).readTag()) + .getList("bedrock_mappings", NbtType.COMPOUND); } catch (Exception e) { throw new AssertionError("Unable to load Java block mappings", e); } @@ -399,56 +409,29 @@ public final class BlockRegistryPopulator { 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()) { + if (MIN_CUSTOM_RUNTIME_ID < blocksNbt.size()) { throw new RuntimeException("Non vanilla custom block state overrides runtime ID must start after the last vanilla block state (" + JAVA_BLOCKS_SIZE + ")"); } JAVA_BLOCKS_SIZE = maxCustomRuntimeID + 1; // Runtime ids start at 0, so we need to add 1 } - BlockRegistries.JAVA_BLOCKS.set(new BlockMapping[JAVA_BLOCKS_SIZE]); // Set array size to number of blockstates - - Deque cleanIdentifiers = new ArrayDeque<>(); - int javaRuntimeId = -1; int waterRuntimeId = -1; - Iterator> blocksIterator = blocksJson.fields(); - while (blocksIterator.hasNext()) { + for (BlockState javaBlockState : BlockRegistries.BLOCK_STATES.get()) { javaRuntimeId++; - Map.Entry entry = blocksIterator.next(); - String javaId = entry.getKey(); + String javaId = javaBlockState.toString().intern(); - BlockMapping.BlockMappingBuilder builder = BlockMapping.builder(); + BlockStateValues.storeBlockStateValues(javaId, javaRuntimeId); - JsonNode pickItemNode = entry.getValue().get("pick_item"); - if (pickItemNode != null) { - builder.pickItem(pickItemNode.textValue().intern()); - } - - JsonNode hasBlockEntityNode = entry.getValue().get("has_block_entity"); - if (hasBlockEntityNode != null) { - builder.isBlockEntity(hasBlockEntityNode.booleanValue()); - } else { - builder.isBlockEntity(false); - } - - BlockStateValues.storeBlockStateValues(entry.getKey(), javaRuntimeId, entry.getValue()); - - String cleanJavaIdentifier = BlockUtils.getCleanIdentifier(entry.getKey()); - String bedrockIdentifier = entry.getValue().get("bedrock_identifier").asText(); - - if (!cleanJavaIdentifier.equals(cleanIdentifiers.peekLast())) { - cleanIdentifiers.add(cleanJavaIdentifier.intern()); - } - - builder.javaIdentifier(javaId); + //String cleanJavaIdentifier = javaBlockState.block().javaIdentifier().toString(); + //String bedrockIdentifier = entry.getValue().get("bedrock_identifier").asText(); BlockRegistries.JAVA_IDENTIFIER_TO_ID.register(javaId, javaRuntimeId); - BlockRegistries.JAVA_BLOCKS.register(javaRuntimeId, builder.build()); // 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.JAVA_TO_BEDROCK_IDENTIFIERS.register(cleanJavaIdentifier.intern(), bedrockIdentifier.intern()); if ("minecraft:water[level=0]".equals(javaId)) { waterRuntimeId = javaRuntimeId; @@ -461,7 +444,7 @@ public final class BlockRegistryPopulator { BlockStateValues.JAVA_WATER_ID = waterRuntimeId; if (!BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().isEmpty()) { - Set usedNonVanillaRuntimeIDs = new HashSet<>(); + IntSet usedNonVanillaRuntimeIDs = new IntOpenHashSet(); for (JavaBlockState javaBlockState : BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().keySet()) { if (!usedNonVanillaRuntimeIDs.add(javaBlockState.javaId())) { @@ -473,11 +456,6 @@ public final class BlockRegistryPopulator { String javaId = javaBlockState.identifier(); int stateRuntimeId = javaBlockState.javaId(); String pistonBehavior = javaBlockState.pistonBehavior(); - BlockMapping blockMapping = BlockMapping.builder() - .pickItem(javaBlockState.pickItem()) - .isNonVanilla(true) - .javaIdentifier(javaId) - .build(); Block.Builder builder = Block.builder() .destroyTime(javaBlockState.blockHardness()) @@ -492,23 +470,25 @@ public final class BlockRegistryPopulator { String pickItem = javaBlockState.pickItem(); Block block = new Block(cleanJavaIdentifier, builder) { @Override - public Item asItem() { + public ItemStack pickItem(BlockState state) { if (this.item == null) { - return Registries.JAVA_ITEM_IDENTIFIERS.get(pickItem); + this.item = Registries.JAVA_ITEM_IDENTIFIERS.get(pickItem); + if (this.item == null) { + GeyserImpl.getInstance().getLogger().warning("We could not find item " + pickItem + + " for getting the item for block " + javaBlockState.identifier()); + this.item = Items.AIR; + } } - return this.item; + return new ItemStack(this.item.javaId()); } }; + block.setJavaId(javaBlockState.stateGroupId()); String bedrockIdentifier = customBlockState.block().identifier(); - if (!cleanJavaIdentifier.equals(cleanIdentifiers.peekLast())) { - cleanIdentifiers.add(cleanJavaIdentifier.intern()); - } - - BlockRegistries.JAVA_BLOCKS_TO_RENAME.get().add(javaBlockState.stateGroupId(), block); //TODO don't allow duplicates, allow blanks + BlockRegistries.JAVA_BLOCKS.get().add(javaBlockState.stateGroupId(), block); //TODO don't allow duplicates, allow blanks BlockRegistries.JAVA_IDENTIFIER_TO_ID.register(javaId, stateRuntimeId); - BlockRegistries.JAVA_BLOCKS.register(stateRuntimeId, blockMapping); + BlockRegistries.BLOCK_STATES.register(stateRuntimeId, new BlockState(block, stateRuntimeId)); // 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 @@ -516,7 +496,7 @@ public final class BlockRegistryPopulator { } } - BLOCKS_JSON = blocksJson; + BLOCKS_NBT = blocksNbt; JsonNode blockInteractionsJson; try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow("mappings/interactions.json")) { @@ -537,29 +517,11 @@ public final class BlockRegistryPopulator { return blockStateSet; } - private static NbtMap buildBedrockState(JsonNode node) { + private static NbtMap buildBedrockState(BlockState state, NbtMap nbt) { NbtMapBuilder tagBuilder = NbtMap.builder(); - String bedrockIdentifier = node.get("bedrock_identifier").textValue(); + String bedrockIdentifier = "minecraft:" + nbt.getString("bedrock_identifier", state.block().javaIdentifier().value()); tagBuilder.putString("name", bedrockIdentifier); - - NbtMapBuilder statesBuilder = NbtMap.builder(); - - // check for states - JsonNode states = node.get("bedrock_states"); - if (states != null) { - Iterator> statesIterator = states.fields(); - - while (statesIterator.hasNext()) { - Map.Entry stateEntry = statesIterator.next(); - JsonNode stateValue = stateEntry.getValue(); - switch (stateValue.getNodeType()) { - case BOOLEAN -> statesBuilder.putBoolean(stateEntry.getKey(), stateValue.booleanValue()); - case STRING -> statesBuilder.putString(stateEntry.getKey(), stateValue.textValue()); - case NUMBER -> statesBuilder.putInt(stateEntry.getKey(), stateValue.intValue()); - } - } - } - tagBuilder.put("states", statesBuilder.build()); + tagBuilder.put("states", nbt.getCompound("state")); return tagBuilder.build(); } diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/BlockMappings.java b/core/src/main/java/org/geysermc/geyser/registry/type/BlockMappings.java index 2fe808070..e4b7111b3 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 @@ -35,6 +35,7 @@ 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 org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.level.block.type.BlockState; import java.util.List; @@ -59,7 +60,7 @@ public class BlockMappings implements DefinitionRegistry { BlockDefinition mobSpawnerBlock; Map itemFrames; - Map flowerPotBlocks; + Map flowerPotBlocks; Set jigsawStates; Map structureBlockStates; 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 5b208a41f..a40a1156d 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,18 +25,20 @@ 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; import lombok.Data; import lombok.Getter; import lombok.RequiredArgsConstructor; +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.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.level.block.property.Properties; +import org.geysermc.geyser.level.block.type.BlockState; +import org.geysermc.geyser.level.block.type.WallSkullBlock; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.type.CustomSkull; import org.geysermc.geyser.session.GeyserSession; @@ -80,7 +82,7 @@ public class SkullCache { this.skullRenderDistanceSquared = distance * distance; } - public Skull putSkull(Vector3i position, UUID uuid, String texturesProperty, int blockState) { + public Skull putSkull(Vector3i position, UUID uuid, String texturesProperty, BlockState blockState) { Skull skull = skulls.computeIfAbsent(position, Skull::new); skull.uuid = uuid; if (!texturesProperty.equals(skull.texturesProperty)) { @@ -147,7 +149,7 @@ public class SkullCache { } } - public Skull updateSkull(Vector3i position, int blockState) { + public Skull updateSkull(Vector3i position, BlockState blockState) { Skull skull = skulls.get(position); if (skull != null) { putSkull(position, skull.uuid, skull.texturesProperty, blockState); @@ -248,17 +250,14 @@ public class SkullCache { lastPlayerPosition = null; } - private @Nullable BlockDefinition translateCustomSkull(String skinHash, int blockState) { + private @Nullable BlockDefinition translateCustomSkull(String skinHash, BlockState 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); + if (blockState.block() instanceof WallSkullBlock) { + customBlockState = customSkull.getWallBlockState(WallSkullBlock.getDegrees(blockState)); } else { - customBlockState = customSkull.getFloorBlockState(floorRotation); + customBlockState = customSkull.getFloorBlockState(blockState.getValue(Properties.ROTATION_16)); } return session.getBlockMappings().getCustomBlockStateDefinitions().get(customBlockState); @@ -273,7 +272,7 @@ public class SkullCache { private String texturesProperty; private String skinHash; - private int blockState; + private BlockState blockState; private BlockDefinition blockDefinition; private SkullPlayerEntity entity; 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 cb973fa18..4c49c8e5a 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 @@ -36,10 +36,13 @@ import org.cloudburstmc.protocol.bedrock.packet.ContainerOpenPacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.geyser.inventory.Container; import org.geysermc.geyser.inventory.Inventory; +import org.geysermc.geyser.level.block.Blocks; +import org.geysermc.geyser.level.block.property.ChestType; +import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.registry.BlockRegistries; -import org.geysermc.geyser.registry.type.BlockMapping; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator; import org.geysermc.geyser.translator.level.block.entity.DoubleChestBlockEntityTranslator; import org.geysermc.geyser.util.InventoryUtils; @@ -55,24 +58,17 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator { public boolean prepareInventory(GeyserSession session, Inventory inventory) { // 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()); - if (!BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get().containsKey(javaBlockId)) { - 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")) { + BlockState state = session.getGeyser().getWorldManager().blockAt(session, session.getLastInteractionBlockPosition()); + if (!BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get().containsKey(state.javaId())) { + if (state.block() == Blocks.CHEST || state.block() == Blocks.TRAPPED_CHEST + && state.getValue(Properties.CHEST_TYPE) != ChestType.SINGLE) { inventory.setHolderPosition(session.getLastInteractionBlockPosition()); - ((Container) inventory).setUsingRealBlock(true, javaBlockString[0]); + ((Container) inventory).setUsingRealBlock(true, state.block()); - 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 = BlockEntityTranslator.getConstantBedrockTag("Chest", session.getLastInteractionBlockPosition()) + .putString("CustomName", inventory.getTitle()); - BlockState blockState = BlockState.of(javaBlockId); - DoubleChestBlockEntityTranslator.translateChestValue(tag, blockState, + DoubleChestBlockEntityTranslator.translateChestValue(tag, state, session.getLastInteractionBlockPosition().getX(), session.getLastInteractionBlockPosition().getZ()); BlockEntityDataPacket dataPacket = new BlockEntityDataPacket(); 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 c03ae8ef0..cdbb20c44 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 @@ -33,9 +33,9 @@ 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.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.level.block.type.BlockState; +import org.geysermc.geyser.level.block.type.SkullBlock; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.SkullCache; import org.geysermc.geyser.skin.SkinProvider; @@ -53,17 +53,12 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements @Override public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) { - byte skullVariant = BlockStateValues.getSkullVariant(blockState.javaId()); // TODO - // Just in case... - if (skullVariant == -1) { - skullVariant = 0; - } Integer rotation = blockState.getValue(Properties.ROTATION_16); if (rotation != null) { - // Could be a wall skull block + // Could be a wall skull block otherwise, which has rotation in its Bedrock state bedrockNbt.putFloat("Rotation", rotation * 22.5f); } - bedrockNbt.putByte("SkullType", skullVariant); + bedrockNbt.putByte("SkullType", (byte) (blockState.block() instanceof SkullBlock skull ? skull.skullType().bedrockId() : 0)); if (blockState.getValue(Properties.POWERED)) { bedrockNbt.putBoolean("MouthMoving", true); } @@ -106,7 +101,7 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements return CompletableFuture.completedFuture(texture); } - public static @Nullable BlockDefinition translateSkull(GeyserSession session, NbtMap javaNbt, Vector3i blockPosition, int blockState) { + public static @Nullable BlockDefinition translateSkull(GeyserSession session, NbtMap javaNbt, Vector3i blockPosition, BlockState blockState) { NbtMap profile = javaNbt.getCompound("profile"); if (profile.isEmpty()) { session.getSkullCache().removeSkull(blockPosition); @@ -150,7 +145,7 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements return null; } - private static void putSkull(GeyserSession session, Vector3i blockPosition, UUID uuid, String texturesProperty, int blockState) { + private static void putSkull(GeyserSession session, Vector3i blockPosition, UUID uuid, String texturesProperty, BlockState blockState) { SkullCache.Skull skull = session.getSkullCache().putSkull(blockPosition, uuid, texturesProperty, blockState); if (skull.getBlockDefinition() != null) { UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); 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 be3af2061..0a721e4b0 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 @@ -32,7 +32,7 @@ import org.geysermc.geyser.entity.type.ItemFrameEntity; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.level.block.type.BannerBlock; -import org.geysermc.geyser.level.block.type.Block; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; @@ -45,10 +45,10 @@ public class BedrockBlockPickRequestTranslator extends PacketTranslator session.ensureInEventLoop(() -> { if (components == null) { @@ -73,7 +73,7 @@ public class BedrockBlockPickRequestTranslator extends PacketTranslator { @@ -77,9 +78,9 @@ public class BedrockLevelSoundEventTranslator extends PacketTranslator { @@ -102,7 +100,7 @@ public class JavaBlockUpdateTranslator extends PacketTranslator> 4) - (bedrockDimension.minY() >> 4); int subChunkIndex = (y >> 4) + (bedrockDimension.minY() >> 4); 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 7e1227f6c..72fcb4fa6 100644 --- a/core/src/main/java/org/geysermc/geyser/util/StatisticsUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/StatisticsUtils.java @@ -94,7 +94,7 @@ public class StatisticsUtils { for (Object2IntMap.Entry entry : session.getStatistics().object2IntEntrySet()) { if (entry.getKey() instanceof BreakBlockStatistic statistic) { - Block block = BlockRegistries.JAVA_BLOCKS_TO_RENAME.get(statistic.getId()); + Block block = BlockRegistries.JAVA_BLOCKS.get(statistic.getId()); if (block != null) { String identifier = "block.minecraft." + block.javaIdentifier().value(); content.add(identifier + ": " + entry.getIntValue()); 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 deleted file mode 100644 index dc4545529..000000000 --- a/core/src/main/java/org/geysermc/geyser/util/collection/FixedInt2BooleanMap.java +++ /dev/null @@ -1,120 +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.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; - - @Override - public int size() { - return value.length; - } - - @Override - public ObjectSet int2BooleanEntrySet() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean get(int i) { - return getOrDefault(i, defRetValue); - } - - @Override - public boolean getOrDefault(int key, boolean defaultValue) { - int offset = key - start; - if (offset < 0 || offset >= value.length) { - return defaultValue; - } - - return value[offset]; - } - - @Override - public boolean put(int key, boolean value) { - if (start == -1) { - start = key; - this.value = new boolean[] {value}; - } else { - int offset = key - start; - if (offset >= 0 && offset < this.value.length) { - boolean curr = this.value[offset]; - this.value[offset] = value; - return curr; - } else if (offset != this.value.length) { - throw new IndexOutOfBoundsException("Expected: " + (this.value.length + start) + ", got " + key); - } - - boolean[] newValue = new boolean[offset + 1]; - System.arraycopy(this.value, 0, newValue, 0, this.value.length); - this.value = newValue; - this.value[offset] = value; - } - - return this.defRetValue; - } - - @Override - public boolean containsKey(int k) { - int offset = k - start; - return offset >= 0 && offset < value.length; - } - - @Override - public boolean containsValue(boolean v) { - for (boolean b : value) { - if (b == v) { - return true; - } - } - - return false; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder("{"); - int index = start; - for (boolean b : value) { - builder.append(index++).append("=>").append(b); - if (index < value.length + start) { - // Add commas while there are still more entries in the list - builder.append(", "); - } - } - return builder.append('}').toString(); - } -} 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 deleted file mode 100644 index 46cb2a2ca..000000000 --- a/core/src/main/java/org/geysermc/geyser/util/collection/FixedInt2ByteMap.java +++ /dev/null @@ -1,121 +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.collection; - -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; - - @Override - public int size() { - return value.length; - } - - @Override - public ObjectSet int2ByteEntrySet() { - throw new UnsupportedOperationException(); - } - - @Override - public byte get(int i) { - return getOrDefault(i, defRetValue); - } - - @Override - public byte getOrDefault(int key, byte defaultValue) { - int offset = key - start; - if (offset < 0 || offset >= value.length) { - return defaultValue; - } - - return value[offset]; - } - - @Override - public byte put(int key, byte value) { - if (start == -1) { - start = key; - this.value = new byte[] {value}; - } else { - int offset = key - start; - if (offset >= 0 && offset < this.value.length) { - byte curr = this.value[offset]; - this.value[offset] = value; - return curr; - } else if (offset != this.value.length) { - throw new IndexOutOfBoundsException("Expected: " + (this.value.length + start) + ", got " + key); - } - - byte[] newValue = new byte[offset + 1]; - System.arraycopy(this.value, 0, newValue, 0, this.value.length); - this.value = newValue; - this.value[offset] = value; - } - - return this.defRetValue; - } - - @Override - public boolean containsKey(int k) { - int offset = k - start; - return offset >= 0 && offset < value.length; - } - - @Override - public boolean containsValue(byte v) { - for (byte i : value) { - if (i == v) { - return true; - } - } - - return false; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder("{"); - int index = start; - for (byte b : value) { - builder.append(index++).append("=>").append(b); - if (index < value.length + start) { - // Add commas while there are still more entries in the list - builder.append(", "); - } - } - return builder.append('}').toString(); - } -} 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 deleted file mode 100644 index 4a27d51a9..000000000 --- a/core/src/main/java/org/geysermc/geyser/util/collection/FixedInt2IntMap.java +++ /dev/null @@ -1,120 +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.collection; - -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; - } - - @Override - public ObjectSet int2IntEntrySet() { - throw new UnsupportedOperationException(); - } - - @Override - public int get(int i) { - return getOrDefault(i, defRetValue); - } - - @Override - public int getOrDefault(int key, int defaultValue) { - int offset = key - start; - if (offset < 0 || offset >= value.length) { - return defaultValue; - } - - return value[offset]; - } - - @Override - public int put(int key, int value) { - if (start == -1) { - start = key; - this.value = new int[] {value}; - } else { - int offset = key - start; - if (offset >= 0 && offset < this.value.length) { - int curr = this.value[offset]; - this.value[offset] = value; - return curr; - } else if (offset != this.value.length) { - throw new IndexOutOfBoundsException("Expected: " + (this.value.length + start) + ", got " + key); - } - - int[] newValue = new int[offset + 1]; - System.arraycopy(this.value, 0, newValue, 0, this.value.length); - this.value = newValue; - this.value[offset] = value; - } - - return this.defRetValue; - } - - @Override - public boolean containsKey(int k) { - int offset = k - start; - return offset >= 0 && offset < value.length; - } - - @Override - public boolean containsValue(int v) { - for (int i : value) { - if (i == v) { - return true; - } - } - - return false; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder("{"); - int index = start; - for (int i : value) { - builder.append(index++).append("=>").append(i); - if (index < value.length + start) { - // Add commas while there are still more entries in the list - builder.append(", "); - } - } - return builder.append('}').toString(); - } -} 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 deleted file mode 100644 index 42d0da803..000000000 --- a/core/src/main/java/org/geysermc/geyser/util/collection/LecternHasBookMap.java +++ /dev/null @@ -1,75 +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.collection; - -import org.cloudburstmc.math.vector.Vector3i; -import org.cloudburstmc.nbt.NbtMap; -import org.geysermc.erosion.util.LecternUtils; -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. - */ - public void handleBlockChange(GeyserSession session, int blockState, Vector3i position) { - WorldManager worldManager = session.getGeyser().getWorldManager(); - - int offset = blockState - this.start; - if (offset < 0 || offset >= this.value.length) { - // Block state is out of bounds of this map - lectern has been destroyed, if it existed - if (!worldManager.shouldExpectLecternHandled(session)) { - session.getLecternCache().remove(position); - } - return; - } - - boolean newLecternHasBook; - if (worldManager.shouldExpectLecternHandled(session)) { - worldManager.sendLecternData(session, position.getX(), position.getY(), position.getZ()); - } else if ((newLecternHasBook = this.value[offset]) != this.get(worldManager.getBlockAt(session, position))) { - // newLecternHasBook = the new lectern block state's "has book" toggle. - if (newLecternHasBook) { - worldManager.sendLecternData(session, position.getX(), position.getY(), position.getZ()); - } else { - session.getLecternCache().remove(position); - NbtMap newLecternTag = LecternUtils.getBaseLecternTag(position.getX(), position.getY(), position.getZ(), 0).build(); - BlockEntityUtils.updateBlockEntity(session, newLecternTag, position); - } - } - } -} 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 deleted file mode 100644 index 46fa5df11..000000000 --- a/core/src/main/java/org/geysermc/geyser/util/collection/package-info.java +++ /dev/null @@ -1,34 +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 - */ - -/** - * 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 - * size and its "start" integer. - */ -package org.geysermc.geyser.util.collection; \ No newline at end of file diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings index 6b661f0d5..968a22bba 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 6b661f0d517d895aebc1f55a25d2c86f033beb1d +Subproject commit 968a22bbab02d7d003c5b451a40d8bb2439b0d97 diff --git a/core/src/test/java/org/geysermc/geyser/util/collection/GeyserCollectionsTest.java b/core/src/test/java/org/geysermc/geyser/util/collection/GeyserCollectionsTest.java deleted file mode 100644 index 639c79331..000000000 --- a/core/src/test/java/org/geysermc/geyser/util/collection/GeyserCollectionsTest.java +++ /dev/null @@ -1,181 +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.collection; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; - -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -public class GeyserCollectionsTest { - private final byte[] bytes = new byte[] {(byte) 5, (byte) 4, (byte) 3, (byte) 2, (byte) 2, (byte) 1}; - private final boolean[] booleans = new boolean[] {true, false, false, true}; - private final int[] ints = new int[] {76, 3006, 999, 2323, 888, 0, 111, 999}; - - private final int[] startBlockRanges = new int[] {0, 70, 600, 450, 787, 1980}; - - @Test - public void testBytes() { - for (int startRange : startBlockRanges) { - testBytes(startRange, new FixedInt2ByteMap()); - } - } - - private void testBytes(final int start, final FixedInt2ByteMap map) { - int index = start; - for (byte b : bytes) { - map.put(index++, b); - } - - int lastKey = index; - - // Easy, understandable out-of-bounds checks - Assertions.assertFalse(map.containsKey(lastKey), "Map contains key bigger by one!"); - Assertions.assertTrue(map.containsKey(lastKey - 1), "Map doesn't contain final key!"); - - // Ensure the first and last values do not throw an exception on get, and test getOrDefault - map.get(start - 1); - map.get(lastKey); - Assertions.assertEquals(map.getOrDefault(start - 1, Byte.MAX_VALUE), Byte.MAX_VALUE); - Assertions.assertEquals(map.getOrDefault(lastKey, Byte.MAX_VALUE), Byte.MAX_VALUE); - Assertions.assertEquals(map.getOrDefault(lastKey, Byte.MIN_VALUE), Byte.MIN_VALUE); - - Assertions.assertEquals(map.size(), bytes.length); - - for (int i = start; i < bytes.length; i++) { - Assertions.assertTrue(map.containsKey(i)); - Assertions.assertEquals(map.get(i), bytes[i - start]); - } - - for (int i = start - 1; i >= (start - 6); i--) { - // Lower than expected check - Assertions.assertFalse(map.containsKey(i), i + " is in a map that starts with " + start); - } - - for (int i = bytes.length + start; i < bytes.length + 5 + start; i++) { - // Higher than expected check - Assertions.assertFalse(map.containsKey(i), i + " is in a map that ends with " + (start + bytes.length)); - } - - for (byte b : bytes) { - Assertions.assertTrue(map.containsValue(b)); - } - } - - @Test - public void testBooleans() { - for (int startRange : startBlockRanges) { - testBooleans(startRange, new FixedInt2BooleanMap()); - } - } - - private void testBooleans(final int start, final FixedInt2BooleanMap map) { - int index = start; - for (boolean b : booleans) { - map.put(index++, b); - } - - int lastKey = index; - - // Easy, understandable out-of-bounds checks - Assertions.assertFalse(map.containsKey(lastKey), "Map contains key bigger by one!"); - Assertions.assertTrue(map.containsKey(lastKey - 1), "Map doesn't contain final key!"); - - // Ensure the first and last values do not throw an exception on get - map.get(start - 1); - map.get(lastKey); - Assertions.assertTrue(map.getOrDefault(lastKey, true)); - - Assertions.assertEquals(map.size(), booleans.length); - - for (int i = start; i < booleans.length; i++) { - Assertions.assertTrue(map.containsKey(i)); - Assertions.assertEquals(map.get(i), booleans[i - start]); - } - - for (int i = start - 1; i >= (start - 6); i--) { - // Lower than expected check - Assertions.assertFalse(map.containsKey(i), i + " is in a map that starts with " + start); - } - - for (int i = booleans.length + start; i < booleans.length + start + 5; i++) { - // Higher than expected check - Assertions.assertFalse(map.containsKey(i), i + " is in a map that ends with " + (start + booleans.length)); - } - - for (boolean b : booleans) { - Assertions.assertTrue(map.containsValue(b)); - } - } - - @Test - public void testInts() { - for (int startRange : startBlockRanges) { - testInts(startRange, new FixedInt2IntMap()); - } - } - - private void testInts(final int start, final FixedInt2IntMap map) { - int index = start; - for (int i : ints) { - map.put(index++, i); - } - - int lastKey = index; - - // Easy, understandable out-of-bounds checks - Assertions.assertFalse(map.containsKey(lastKey), "Map contains key bigger by one!"); - Assertions.assertTrue(map.containsKey(lastKey - 1), "Map doesn't contain final key!"); - - // Ensure the first and last values do not throw an exception on get, and test getOrDefault - map.get(start - 1); - map.get(lastKey); - Assertions.assertEquals(map.getOrDefault(start - 1, Integer.MAX_VALUE), Integer.MAX_VALUE); - Assertions.assertEquals(map.getOrDefault(lastKey, Integer.MAX_VALUE), Integer.MAX_VALUE); - Assertions.assertEquals(map.getOrDefault(lastKey, Integer.MIN_VALUE), Integer.MIN_VALUE); - - Assertions.assertEquals(map.size(), ints.length); - - for (int i = start; i < ints.length; i++) { - Assertions.assertTrue(map.containsKey(i)); - Assertions.assertEquals(map.get(i), ints[i - start]); - } - - for (int i = start - 1; i >= (start - 6); i--) { - // Lower than expected check - Assertions.assertFalse(map.containsKey(i), i + " is in a map that starts with " + start); - } - - for (int i = ints.length + start; i < ints.length + 5 + start; i++) { - // Higher than expected check - Assertions.assertFalse(map.containsKey(i), i + " is in a map that ends with " + (start + ints.length)); - } - - for (int i : ints) { - Assertions.assertTrue(map.containsValue(i)); - } - } -} From 1b075badcedbba8332842562c651f8bf9c24d1c3 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sun, 19 May 2024 23:15:52 -0400 Subject: [PATCH 021/233] Actually implement adventure mode predicates, kind of. If it's just block IDs, it'll work. --- .../geyser/registry/BlockRegistries.java | 9 +-- .../geysermc/geyser/registry/Registries.java | 1 - .../populator/BlockRegistryPopulator.java | 36 +++++++---- .../geyser/registry/type/BlockMappings.java | 6 ++ .../translator/item/ItemTranslator.java | 64 +++++++++++-------- .../protocol/java/JavaCommandsTranslator.java | 11 +--- gradle/libs.versions.toml | 2 +- 7 files changed, 71 insertions(+), 58 deletions(-) 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 93ac5e457..2f15094ef 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java +++ b/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java @@ -66,11 +66,6 @@ public class BlockRegistries { */ public static final ListRegistry BLOCK_STATES = ListRegistry.create(RegistryLoaders.empty(ArrayList::new)); - /** - * A mapped registry which stores Java to Bedrock block identifiers. - */ - public static final SimpleMappedRegistry JAVA_TO_BEDROCK_IDENTIFIERS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new)); - /** * A mapped registry containing which holds block IDs to its {@link BlockCollision}. */ @@ -89,6 +84,9 @@ public class BlockRegistries { /** * A registry containing all the waterlogged blockstates. + * Properties.WATERLOGGED should not be relied on for two reasons: + * - Custom blocks + * - Seagrass, kelp, and bubble columns are assumed waterlogged and don't have a waterlogged property */ public static final SimpleRegistry WATERLOGGED = SimpleRegistry.create(RegistryLoaders.empty(BitSet::new)); @@ -144,7 +142,6 @@ public class BlockRegistries { CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.CUSTOM_REGISTRATION); BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.INIT_BEDROCK); BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.POST_INIT); - System.out.println("Block registries loaded"); } public static void init() { 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 7f0d9013a..54d013140 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/Registries.java +++ b/core/src/main/java/org/geysermc/geyser/registry/Registries.java @@ -204,6 +204,5 @@ public final class Registries { biomesNbt.put(key, value.build()); } BIOMES_NBT.set(biomesNbt.build()); - System.out.println("Registries loaded"); } } 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 a0af4cfa0..5f50f4f68 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 @@ -236,6 +236,10 @@ public final class BlockRegistryPopulator { GeyserBedrockBlock[] javaToBedrockBlocks = new GeyserBedrockBlock[JAVA_BLOCKS_SIZE]; GeyserBedrockBlock[] javaToVanillaBedrockBlocks = new GeyserBedrockBlock[JAVA_BLOCKS_SIZE]; + //List javaToBedrockIdentifiers = new ArrayList<>(BlockRegistries.JAVA_BLOCKS.get().size()); + var javaToBedrockIdentifiers = new Int2ObjectOpenHashMap(); + Block lastBlockSeen = null; + // Stream isn't ideal. List javaPottable = BlockRegistries.JAVA_BLOCKS.get() .parallelStream() @@ -291,27 +295,35 @@ public final class BlockRegistryPopulator { case "minecraft:moving_piston[facing=north,type=normal]" -> movingBlockDefinition = bedrockDefinition; } - if (blockState.block() == Blocks.JIGSAW) { + Block block = blockState.block(); + if (block != lastBlockSeen) { + lastBlockSeen = block; + String bedrockName = bedrockDefinition.getState().getString("name"); + if (!block.javaIdentifier().toString().equals(bedrockName)) { + javaToBedrockIdentifiers.put(block.javaId(), bedrockName.substring("minecraft:".length()).intern()); + } + } + + if (block == Blocks.JIGSAW) { jigsawDefinitions.add(bedrockDefinition); } - if (blockState.block() == Blocks.STRUCTURE_BLOCK) { + if (block == Blocks.STRUCTURE_BLOCK) { String mode = blockState.getValue(Properties.STRUCTUREBLOCK_MODE); structureBlockDefinitions.put(mode.toUpperCase(Locale.ROOT), bedrockDefinition); } boolean waterlogged = blockState.getValue(Properties.WATERLOGGED, false) - || blockState.block() == Blocks.BUBBLE_COLUMN || blockState.block() == Blocks.KELP || blockState.block() == Blocks.SEAGRASS; + || block == Blocks.BUBBLE_COLUMN || block == Blocks.KELP || block == Blocks.SEAGRASS; if (waterlogged) { - int finalJavaRuntimeId = javaRuntimeId; - BlockRegistries.WATERLOGGED.register(set -> set.set(finalJavaRuntimeId)); + BlockRegistries.WATERLOGGED.get().set(javaRuntimeId); } // Get the tag needed for non-empty flower pots - if (javaPottable.contains(blockState.block())) { + if (javaPottable.contains(block)) { // Specifically NOT putIfAbsent - mangrove propagule breaks otherwise - flowerPotBlocks.put(blockState.block(), blockStates.get(bedrockDefinition.getRuntimeId())); + flowerPotBlocks.put(block, blockStates.get(bedrockDefinition.getRuntimeId())); } javaToVanillaBedrockBlocks[javaRuntimeId] = vanillaBedrockDefinition; @@ -367,9 +379,12 @@ public final class BlockRegistryPopulator { javaToVanillaBedrockBlocks[stateRuntimeId] = bedrockDefinition; // TODO: Check this? javaToBedrockBlocks[stateRuntimeId] = bedrockDefinition; + javaToBedrockIdentifiers.put(entry.getKey().stateGroupId(), entry.getValue().block().identifier()); } } + javaToBedrockIdentifiers.trim(); + // Loop around again to find all item frame runtime IDs Object2ObjectMaps.fastForEach(blockStateOrderedMap, entry -> { String name = entry.getKey().getString("name"); @@ -381,6 +396,7 @@ public final class BlockRegistryPopulator { BlockRegistries.BLOCKS.register(palette.valueInt(), builder.bedrockRuntimeMap(bedrockRuntimeMap) .javaToBedrockBlocks(javaToBedrockBlocks) .javaToVanillaBedrockBlocks(javaToVanillaBedrockBlocks) + .javaToBedrockIdentifiers(javaToBedrockIdentifiers) .stateDefinitionMap(blockStateOrderedMap) .itemFrames(itemFrames) .flowerPotBlocks(flowerPotBlocks) @@ -484,15 +500,9 @@ public final class BlockRegistryPopulator { }; block.setJavaId(javaBlockState.stateGroupId()); - String bedrockIdentifier = customBlockState.block().identifier(); - BlockRegistries.JAVA_BLOCKS.get().add(javaBlockState.stateGroupId(), block); //TODO don't allow duplicates, allow blanks BlockRegistries.JAVA_IDENTIFIER_TO_ID.register(javaId, stateRuntimeId); BlockRegistries.BLOCK_STATES.register(stateRuntimeId, new BlockState(block, stateRuntimeId)); - - // 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()); } } 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 e4b7111b3..f618fde46 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 @@ -52,6 +52,12 @@ public class BlockMappings implements DefinitionRegistry { GeyserBedrockBlock[] javaToBedrockBlocks; GeyserBedrockBlock[] javaToVanillaBedrockBlocks; + /** + * Java block ID -> Bedrock block ID (without minecraft:), IF they are different + * While Bedrock is progressing slowly through their flattening, some Bedrock identifiers may differ. + */ + Int2ObjectMap javaToBedrockIdentifiers; + Map stateDefinitionMap; GeyserBedrockBlock[] bedrockRuntimeMap; int[] remappedVanillaIds; 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 768c94791..251aacba8 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 @@ -42,6 +42,7 @@ 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.level.block.type.Block; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.CustomSkull; @@ -52,20 +53,12 @@ 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 org.geysermc.mcprotocollib.protocol.data.game.item.component.*; import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; public final class ItemTranslator { @@ -185,11 +178,11 @@ public final class ItemTranslator { translateCustomItem(components, builder, bedrockItem); if (components != null) { - // Translate the canDestroy and canPlaceOn Java NBT + // Translate the canDestroy and canPlaceOn Java components AdventureModePredicate canDestroy = components.get(DataComponentType.CAN_BREAK); AdventureModePredicate canPlaceOn = components.get(DataComponentType.CAN_PLACE_ON); - String[] canBreak = getCanModify(canDestroy); - String[] canPlace = getCanModify(canPlaceOn); + String[] canBreak = getCanModify(session, canDestroy); + String[] canPlace = getCanModify(session, canPlaceOn); if (canBreak != null) { builder.canBreak(canBreak); } @@ -325,27 +318,42 @@ public final class ItemTranslator { * @param canModifyJava the list of items in Java * @return the new list of items in Bedrock */ - // TODO this is now more complicated in 1.20.5. Yippee! - private static String @Nullable [] getCanModify(@Nullable AdventureModePredicate canModifyJava) { + // TODO blocks by tag, maybe NBT, maybe properties + // Blocks by tag will be easy enough, most likely, we just need to... save all block tags. + // Probably do that with Guava interning around sessions + private static String @Nullable [] getCanModify(GeyserSession session, @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 location = predicates.get(i).getLocation(); - if (location == null) { - canModifyBedrock[i] = ""; // So it'll serialize - continue; // ??? + if (!predicates.isEmpty()) { + List canModifyBedrock = new ArrayList<>(); // This used to be an array, but we need to be flexible with what blocks can be supported + for (int i = 0; i < predicates.size(); i++) { + HolderSet holderSet = predicates.get(i).getBlocks(); + if (holderSet == null) { + continue; + } + int[] holders = holderSet.getHolders(); + if (holders == null) { + continue; + } + // Holders is an int state of Java block IDs (not block states) + for (int blockId : holders) { + // Get the Bedrock identifier of the item + // This will unfortunately be limited - for example, beds and banners will be translated weirdly + Block block = BlockRegistries.JAVA_BLOCKS.get(blockId); + if (block == null) { + continue; + } + String identifier = session.getBlockMappings().getJavaToBedrockIdentifiers().get(block.javaId()); + if (identifier == null) { + canModifyBedrock.add(block.javaIdentifier().value()); + } else { + canModifyBedrock.add(identifier); + } } - 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:", ""); } - return canModifyBedrock; + return canModifyBedrock.toArray(new String[0]); } return null; } 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 706997402..d9f190197 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 @@ -59,6 +59,7 @@ import java.util.*; @Translator(packet = ClientboundCommandsPacket.class) public class JavaCommandsTranslator extends PacketTranslator { + private static final String[] ALL_BLOCK_NAMES = BlockRegistries.JAVA_BLOCKS.get().stream().map(block -> block.javaIdentifier().toString()).toArray(String[]::new); private static final String[] ALL_EFFECT_IDENTIFIERS = EntityUtils.getAllEffectIdentifiers(); 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"}; @@ -246,7 +247,7 @@ public class JavaCommandsTranslator extends PacketTranslator CommandParam.FILE_PATH; case BOOL -> ENUM_BOOLEAN; case OPERATION -> CommandParam.OPERATOR; // ">=", "==", etc - case BLOCK_STATE -> context.getBlockStates(); + case BLOCK_STATE -> ALL_BLOCK_NAMES; case ITEM_STACK -> context.getItemNames(); case COLOR -> VALID_COLORS; case SCOREBOARD_SLOT -> VALID_SCOREBOARD_SLOTS; @@ -286,7 +287,6 @@ public class JavaCommandsTranslator extends PacketTranslator Date: Mon, 20 May 2024 00:28:40 -0400 Subject: [PATCH 022/233] Add TrapDoorBlock --- .../geysermc/geyser/level/block/Blocks.java | 40 +++++++++---------- .../level/block/type/TrapDoorBlock.java | 32 +++++++++++++++ 2 files changed, 52 insertions(+), 20 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/type/TrapDoorBlock.java diff --git a/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java index 178887754..91f02d65e 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java @@ -655,55 +655,55 @@ public final class Blocks { public static final Block GREEN_STAINED_GLASS = register(new Block("green_stained_glass", builder().destroyTime(0.3f))); public static final Block RED_STAINED_GLASS = register(new Block("red_stained_glass", builder().destroyTime(0.3f))); public static final Block BLACK_STAINED_GLASS = register(new Block("black_stained_glass", builder().destroyTime(0.3f))); - public static final Block OAK_TRAPDOOR = register(new Block("oak_trapdoor", builder().destroyTime(3.0f) + public static final Block OAK_TRAPDOOR = register(new TrapDoorBlock("oak_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block SPRUCE_TRAPDOOR = register(new Block("spruce_trapdoor", builder().destroyTime(3.0f) + public static final Block SPRUCE_TRAPDOOR = register(new TrapDoorBlock("spruce_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block BIRCH_TRAPDOOR = register(new Block("birch_trapdoor", builder().destroyTime(3.0f) + public static final Block BIRCH_TRAPDOOR = register(new TrapDoorBlock("birch_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block JUNGLE_TRAPDOOR = register(new Block("jungle_trapdoor", builder().destroyTime(3.0f) + public static final Block JUNGLE_TRAPDOOR = register(new TrapDoorBlock("jungle_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block ACACIA_TRAPDOOR = register(new Block("acacia_trapdoor", builder().destroyTime(3.0f) + public static final Block ACACIA_TRAPDOOR = register(new TrapDoorBlock("acacia_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block CHERRY_TRAPDOOR = register(new Block("cherry_trapdoor", builder().destroyTime(3.0f) + public static final Block CHERRY_TRAPDOOR = register(new TrapDoorBlock("cherry_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block DARK_OAK_TRAPDOOR = register(new Block("dark_oak_trapdoor", builder().destroyTime(3.0f) + public static final Block DARK_OAK_TRAPDOOR = register(new TrapDoorBlock("dark_oak_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block MANGROVE_TRAPDOOR = register(new Block("mangrove_trapdoor", builder().destroyTime(3.0f) + public static final Block MANGROVE_TRAPDOOR = register(new TrapDoorBlock("mangrove_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block BAMBOO_TRAPDOOR = register(new Block("bamboo_trapdoor", builder().destroyTime(3.0f) + public static final Block BAMBOO_TRAPDOOR = register(new TrapDoorBlock("bamboo_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) @@ -1196,7 +1196,7 @@ public final class Blocks { public static final Block LIGHT = register(new Block("light", builder().destroyTime(-1.0f) .intState(LEVEL, 0, 15) .booleanState(WATERLOGGED))); - public static final Block IRON_TRAPDOOR = register(new Block("iron_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(5.0f) + public static final Block IRON_TRAPDOOR = register(new TrapDoorBlock("iron_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(5.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) @@ -2102,13 +2102,13 @@ public final class Blocks { .booleanState(SOUTH) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block CRIMSON_TRAPDOOR = register(new Block("crimson_trapdoor", builder().destroyTime(3.0f) + public static final Block CRIMSON_TRAPDOOR = register(new TrapDoorBlock("crimson_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block WARPED_TRAPDOOR = register(new Block("warped_trapdoor", builder().destroyTime(3.0f) + public static final Block WARPED_TRAPDOOR = register(new TrapDoorBlock("warped_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) @@ -2583,49 +2583,49 @@ public final class Blocks { .enumState(DOOR_HINGE, "left", "right") .booleanState(OPEN) .booleanState(POWERED))); - public static final Block COPPER_TRAPDOOR = register(new Block("copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) + public static final Block COPPER_TRAPDOOR = register(new TrapDoorBlock("copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block EXPOSED_COPPER_TRAPDOOR = register(new Block("exposed_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) + public static final Block EXPOSED_COPPER_TRAPDOOR = register(new TrapDoorBlock("exposed_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block OXIDIZED_COPPER_TRAPDOOR = register(new Block("oxidized_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) + public static final Block OXIDIZED_COPPER_TRAPDOOR = register(new TrapDoorBlock("oxidized_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block WEATHERED_COPPER_TRAPDOOR = register(new Block("weathered_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) + public static final Block WEATHERED_COPPER_TRAPDOOR = register(new TrapDoorBlock("weathered_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block WAXED_COPPER_TRAPDOOR = register(new Block("waxed_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) + public static final Block WAXED_COPPER_TRAPDOOR = register(new TrapDoorBlock("waxed_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block WAXED_EXPOSED_COPPER_TRAPDOOR = register(new Block("waxed_exposed_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) + public static final Block WAXED_EXPOSED_COPPER_TRAPDOOR = register(new TrapDoorBlock("waxed_exposed_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block WAXED_OXIDIZED_COPPER_TRAPDOOR = register(new Block("waxed_oxidized_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) + public static final Block WAXED_OXIDIZED_COPPER_TRAPDOOR = register(new TrapDoorBlock("waxed_oxidized_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); - public static final Block WAXED_WEATHERED_COPPER_TRAPDOOR = register(new Block("waxed_weathered_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) + public static final Block WAXED_WEATHERED_COPPER_TRAPDOOR = register(new TrapDoorBlock("waxed_weathered_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF, "top", "bottom") .booleanState(OPEN) diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/TrapDoorBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/TrapDoorBlock.java new file mode 100644 index 000000000..a94414ac2 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/TrapDoorBlock.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 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.level.block.type; + +public class TrapDoorBlock extends Block { + public TrapDoorBlock(String javaIdentifier, Builder builder) { + super(javaIdentifier, builder); + } +} From a780eeaae8d7a13c2c198a1880c14f0a704f5fb7 Mon Sep 17 00:00:00 2001 From: gecko10000 <60494179+gecko10000@users.noreply.github.com> Date: Mon, 20 May 2024 10:52:41 -0700 Subject: [PATCH 023/233] Open advancement tab regardless of currently open tab (#4665) --- .../geyser/session/cache/AdvancementsCache.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) 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 da3c83ed4..6769b4330 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 @@ -91,15 +91,13 @@ public class AdvancementsCache { builder.validResultHandler((response) -> { String id = rootAdvancementIds.get(response.clickedButtonId()); if (!id.equals("")) { - if (id.equals(currentAdvancementCategoryId)) { - // The server thinks we are already on this tab - buildAndShowListForm(); - } else { - // Send a packet indicating that we intend to open this particular advancement window + if (!id.equals(currentAdvancementCategoryId)) { + // Send a packet indicating that we are opening this particular advancement window ServerboundSeenAdvancementsPacket packet = new ServerboundSeenAdvancementsPacket(id); session.sendDownstreamGamePacket(packet); - // Wait for a response there } + currentAdvancementCategoryId = id; + buildAndShowListForm(); } }); From db166ad8dec5cc23998eeb2480629c8ca5884a97 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Mon, 20 May 2024 21:26:01 -0400 Subject: [PATCH 024/233] Small optimizations and BlockStateValues reduction --- .../spigot/world/GeyserPistonListener.java | 3 +- .../manager/GeyserSpigotWorldManager.java | 3 +- .../erosion/GeyserboundPacketHandlerImpl.java | 3 +- .../geyser/level/block/BlockStateValues.java | 45 ++------------- .../geysermc/geyser/level/block/Blocks.java | 5 +- .../level/block/property/FrontAndTop.java | 55 +++++++++++++++++++ .../level/block/property/Properties.java | 2 +- .../geyser/registry/ListRegistry.java | 18 ++++++ .../loader/CollisionRegistryLoader.java | 3 +- .../populator/BlockRegistryPopulator.java | 11 +--- .../JigsawBlockBlockEntityTranslator.java | 4 +- .../java/level/JavaBlockEventTranslator.java | 10 ++-- 12 files changed, 97 insertions(+), 65 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/property/FrontAndTop.java 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 2a6dc7a81..963f5bac3 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 @@ -41,6 +41,7 @@ import org.bukkit.event.block.BlockPistonRetractEvent; import org.cloudburstmc.math.vector.Vector3i; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.level.physics.Direction; import org.geysermc.geyser.platform.spigot.world.manager.GeyserSpigotWorldManager; @@ -120,7 +121,7 @@ public class GeyserPistonListener implements Listener { int pistonBlockId = worldManager.getBlockNetworkId(event.getBlock()); // event.getDirection() is unreliable - Direction orientation = BlockStateValues.getPistonOrientation(pistonBlockId); + Direction orientation = BlockState.of(pistonBlockId).getValue(Properties.FACING); session.executeInEventLoop(() -> { PistonCache pistonCache = session.getPistonCache(); 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 a04c60126..f45b68675 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 @@ -42,7 +42,6 @@ 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; @@ -88,7 +87,7 @@ public class GeyserSpigotWorldManager extends WorldManager { Bukkit.getRegionScheduler().execute(this.plugin, block.getLocation(), () -> blockData.complete(block.getBlockData().getAsString())); return BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(blockData.join(), org.geysermc.geyser.level.block.type.Block.JAVA_AIR_ID); } - return BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(block.getBlockData().getAsString(), org.geysermc.geyser.level.block.type.Block.JAVA_AIR_ID); + return BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(block.getBlockData().getAsString(), org.geysermc.geyser.level.block.type.Block.JAVA_AIR_ID); // TODO could just make this a BlockState lookup? } @Override 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 9894a4ba2..c8cbe384b 100644 --- a/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java +++ b/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java @@ -44,6 +44,7 @@ import org.geysermc.erosion.packet.backendbound.BackendboundInitializePacket; import org.geysermc.erosion.packet.backendbound.BackendboundPacket; import org.geysermc.erosion.packet.geyserbound.*; import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.level.physics.Direction; @@ -148,7 +149,7 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke @Override public void handlePistonEvent(GeyserboundPistonEventPacket packet) { - Direction orientation = BlockStateValues.getPistonOrientation(packet.getBlockId()); + Direction orientation = BlockState.of(packet.getBlockId()).getValue(Properties.FACING); Vector3i position = packet.getPos(); boolean isExtend = packet.isExtend(); 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 8bc9cf1e2..d52c46e33 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 @@ -25,7 +25,10 @@ package org.geysermc.geyser.level.block; -import it.unimi.dsi.fastutil.ints.*; +import it.unimi.dsi.fastutil.ints.Int2IntMap; +import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import org.geysermc.geyser.level.block.property.Properties; @@ -36,16 +39,11 @@ import org.geysermc.geyser.level.physics.Direction; import org.geysermc.geyser.level.physics.PistonBehavior; import org.geysermc.geyser.registry.BlockRegistries; -import java.util.Locale; - /** * Used for block entities if the Java block state contains Bedrock block information. */ public final class BlockStateValues { - private static final IntSet HORIZONTAL_FACING_JIGSAWS = new IntOpenHashSet(); - private static final IntSet STICKY_PISTONS = new IntOpenHashSet(); private static final Object2IntMap PISTON_HEADS = new Object2IntOpenHashMap<>(); - private static final Int2ObjectMap PISTON_ORIENTATION = new Int2ObjectOpenHashMap<>(); private static final IntSet ALL_PISTON_HEADS = new IntOpenHashSet(); private static final Int2IntMap WATER_LEVEL = new Int2IntOpenHashMap(); @@ -61,10 +59,6 @@ public final class BlockStateValues { */ public static void storeBlockStateValues(String javaId, int javaBlockState) { if (javaId.contains("piston[")) { // minecraft:moving_piston, minecraft:sticky_piston, minecraft:piston - if (javaId.contains("sticky")) { - STICKY_PISTONS.add(javaBlockState); - } - PISTON_ORIENTATION.put(javaBlockState, getBlockDirection(javaId)); return; } else if (javaId.startsWith("minecraft:piston_head")) { ALL_PISTON_HEADS.add(javaBlockState); @@ -78,27 +72,7 @@ public final class BlockStateValues { String strLevel = javaId.substring(javaId.lastIndexOf("level=") + 6, javaId.length() - 1); int level = Integer.parseInt(strLevel); WATER_LEVEL.put(javaBlockState, level); - return; } - - if (javaId.startsWith("minecraft:jigsaw[orientation=")) { - String blockStateData = javaId.substring(javaId.indexOf("orientation=") + "orientation=".length(), javaId.lastIndexOf('_')); - Direction direction = Direction.valueOf(blockStateData.toUpperCase(Locale.ROOT)); - if (direction.isHorizontal()) { - HORIZONTAL_FACING_JIGSAWS.add(javaBlockState); - } - } - } - - /** - * @return a set of all forward-facing jigsaws, to use as a fallback if NBT is missing. - */ - public static IntSet getHorizontalFacingJigsaws() { - return HORIZONTAL_FACING_JIGSAWS; - } - - public static boolean isStickyPiston(int blockState) { - return STICKY_PISTONS.contains(blockState); } public static boolean isPistonHead(int state) { @@ -116,17 +90,6 @@ public final class BlockStateValues { return PISTON_HEADS.getOrDefault(direction, Block.JAVA_AIR_ID); } - /** - * This is used in GeyserPistonEvents.java and accepts minecraft:piston, - * minecraft:sticky_piston, and minecraft:moving_piston. - * - * @param state The block state of the piston base - * @return The direction in which the piston faces - */ - public static Direction getPistonOrientation(int state) { - return PISTON_ORIENTATION.get(state); - } - /** * Checks if a block sticks to other blocks * (Slime and honey blocks) diff --git a/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java index 91f02d65e..283ca2503 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.level.block; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.level.block.property.ChestType; +import org.geysermc.geyser.level.block.property.FrontAndTop; import org.geysermc.geyser.level.block.type.*; import org.geysermc.geyser.level.physics.Axis; import org.geysermc.geyser.level.physics.Direction; @@ -2169,7 +2170,7 @@ public final class Blocks { public static final Block STRUCTURE_BLOCK = register(new Block("structure_block", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(-1.0f) .enumState(STRUCTUREBLOCK_MODE, "save", "load", "corner", "data"))); public static final Block JIGSAW = register(new Block("jigsaw", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(-1.0f) - .enumState(ORIENTATION, "down_east", "down_north", "down_south", "down_west", "up_east", "up_north", "up_south", "up_west", "west_up", "east_up", "north_up", "south_up"))); + .enumState(ORIENTATION, FrontAndTop.VALUES))); public static final Block COMPOSTER = register(new Block("composter", builder().destroyTime(0.6f) .intState(LEVEL_COMPOSTER, 0, 8))); public static final Block TARGET = register(new Block("target", builder().destroyTime(0.5f) @@ -2799,7 +2800,7 @@ public final class Blocks { .booleanState(WATERLOGGED))); public static final Block CRAFTER = register(new Block("crafter", builder().setBlockEntity().destroyTime(1.5f) .booleanState(CRAFTING) - .enumState(ORIENTATION, "down_east", "down_north", "down_south", "down_west", "up_east", "up_north", "up_south", "up_west", "west_up", "east_up", "north_up", "south_up") + .enumState(ORIENTATION, FrontAndTop.VALUES) .booleanState(TRIGGERED))); public static final Block TRIAL_SPAWNER = register(new Block("trial_spawner", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(50.0f) .booleanState(OMINOUS) diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/FrontAndTop.java b/core/src/main/java/org/geysermc/geyser/level/block/property/FrontAndTop.java new file mode 100644 index 000000000..e674ac424 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/property/FrontAndTop.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 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.level.block.property; + +import org.geysermc.geyser.level.physics.Direction; + +public enum FrontAndTop { + DOWN_EAST(Direction.DOWN), + DOWN_NORTH(Direction.DOWN), + DOWN_SOUTH(Direction.DOWN), + DOWN_WEST(Direction.DOWN), + UP_EAST(Direction.UP), + UP_NORTH(Direction.UP), + UP_SOUTH(Direction.UP), + UP_WEST(Direction.UP), + WEST_UP(Direction.WEST), + EAST_UP(Direction.EAST), + NORTH_UP(Direction.NORTH), + SOUTH_UP(Direction.SOUTH); + + private final boolean horizontal; + + FrontAndTop(Direction front) { + this.horizontal = front.isHorizontal(); + } + + public boolean isHorizontal() { + return horizontal; + } + + public static final FrontAndTop[] VALUES = values(); +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java b/core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java index 339d82f96..7df09003d 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java @@ -74,7 +74,7 @@ public final class Properties { public static final Property FACING_HOPPER = Property.create("facing"); public static final Property HORIZONTAL_FACING = Property.create("facing"); public static final Property FLOWER_AMOUNT = Property.create("flower_amount"); - public static final Property ORIENTATION = Property.create("orientation"); + public static final Property ORIENTATION = Property.create("orientation"); public static final Property ATTACH_FACE = Property.create("face"); public static final Property BELL_ATTACHMENT = Property.create("attachment"); public static final Property EAST_WALL = Property.create("east"); diff --git a/core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java index d13c47ba8..34a78c370 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java +++ b/core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java @@ -28,10 +28,13 @@ package org.geysermc.geyser.registry; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.registry.loader.RegistryLoader; +import java.util.ArrayList; import java.util.List; import java.util.function.Supplier; public class ListRegistry extends Registry> { + private boolean frozen = false; + /** * Creates a new instance of this class with the given input and * {@link RegistryLoader}. The input specified is what the registry @@ -85,9 +88,24 @@ public class ListRegistry extends Registry> { * @return a new value into this registry with the given index. */ public M register(int index, M value) { + if (this.frozen) { + throw new IllegalStateException("Registry should not be modified after frozen!"); + } return this.mappings.set(index, value); } + /** + * Mark this registry as unsuitable for new additions. The backing list will then be optimized for storage. + */ + public void freeze() { + if (!this.frozen) { + this.frozen = true; + if (this.mappings instanceof ArrayList arrayList) { + arrayList.trimToSize(); + } + } + } + /** * Creates a new array registry with the given {@link RegistryLoader}. The * input type is not specified here, meaning the loader return type is either 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 2cd7f82d6..bd98ae0a5 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 @@ -77,7 +77,7 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader blockStates = BlockRegistries.BLOCK_STATES.get(); - List collisions = new ObjectArrayList<>(blockStates.size()); + var collisions = new ObjectArrayList(blockStates.size()); // Map of unique collisions to its instance Map collisionInstances = new Object2ObjectOpenHashMap<>(); @@ -102,6 +102,7 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader { - int blockId = session.getGeyser().getWorldManager().getBlockAt(session, position); - boolean sticky = BlockStateValues.isStickyPiston(blockId); + BlockState state = session.getGeyser().getWorldManager().blockAt(session, position); + boolean sticky = state.is(Blocks.STICKY_PISTON); boolean extended = action != PistonValueType.PUSHING; return new PistonBlockEntity(session, pos, direction, sticky, extended); }); From 0094fa1418e313361b94bc2e13010a9a84f20ab7 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 21 May 2024 14:25:57 -0400 Subject: [PATCH 025/233] BlockState values can now be switched at runtime E.G. Blocks.PISTON_HEAD.defaultBlockState().withValue(FACING, Direction.SOUTH) Some of the inspiration may be thanks to FerriteCore, at least with the shared property keys idea, so thank you to them. --- .../entity/type/FurnaceMinecartEntity.java | 7 +- .../entity/type/SpawnerMinecartEntity.java | 4 +- .../holder/BlockInventoryHolder.java | 33 +- .../geyser/level/block/BlockStateValues.java | 75 +- .../geysermc/geyser/level/block/Blocks.java | 1052 ++++++++--------- .../block/property/BasicEnumProperty.java | 63 + .../level/block/property/BooleanProperty.java | 46 + .../level/block/property/EnumProperty.java | 59 + .../level/block/property/IntegerProperty.java | 59 + .../level/block/property/Properties.java | 228 ++-- .../geyser/level/block/property/Property.java | 12 +- .../geyser/level/block/type/Block.java | 50 +- .../geyser/level/block/type/BlockState.java | 115 +- .../geyser/level/block/type/FurnaceBlock.java | 21 +- .../geyser/level/block/type/HoneyBlock.java | 13 - .../geyser/level/block/type/SpawnerBlock.java | 13 - .../geyser/level/block/type/WaterBlock.java | 9 - .../level/physics/CollisionManager.java | 6 +- .../populator/BlockRegistryPopulator.java | 13 - .../geyser/registry/type/BlockMappings.java | 4 + .../AbstractBlockInventoryTranslator.java | 15 +- .../inventory/AnvilInventoryTranslator.java | 2 +- .../inventory/BeaconInventoryTranslator.java | 11 +- .../inventory/BrewingInventoryTranslator.java | 7 +- .../CartographyInventoryTranslator.java | 3 +- .../inventory/CrafterInventoryTranslator.java | 3 +- .../CraftingInventoryTranslator.java | 3 +- .../EnchantingInventoryTranslator.java | 3 +- .../Generic3X3InventoryTranslator.java | 2 +- .../GrindstoneInventoryTranslator.java | 3 +- .../inventory/HopperInventoryTranslator.java | 3 +- .../inventory/LecternInventoryTranslator.java | 3 +- .../inventory/LoomInventoryTranslator.java | 3 +- .../inventory/OldSmithingTableTranslator.java | 3 +- .../inventory/ShulkerInventoryTranslator.java | 10 +- .../SmithingInventoryTranslator.java | 3 +- .../StonecutterInventoryTranslator.java | 3 +- .../chest/DoubleChestInventoryTranslator.java | 12 +- .../chest/SingleChestInventoryTranslator.java | 11 +- .../AbstractFurnaceInventoryTranslator.java | 6 +- .../BlastFurnaceInventoryTranslator.java | 3 +- .../furnace/FurnaceInventoryTranslator.java | 3 +- .../furnace/SmokerInventoryTranslator.java | 3 +- .../level/block/entity/PistonBlockEntity.java | 41 +- ...BedrockInventoryTransactionTranslator.java | 8 +- .../protocol/java/JavaCommandsTranslator.java | 9 +- gradle/libs.versions.toml | 3 +- 47 files changed, 1160 insertions(+), 901 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/property/BasicEnumProperty.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/property/BooleanProperty.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/property/EnumProperty.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/property/IntegerProperty.java 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 0fc5627ed..e33e6d7b6 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 @@ -28,7 +28,9 @@ package org.geysermc.geyser.entity.type; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.EntityDefinition; -import org.geysermc.geyser.level.block.type.FurnaceBlock; +import org.geysermc.geyser.level.block.Blocks; +import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; @@ -51,7 +53,8 @@ public class FurnaceMinecartEntity extends DefaultBlockMinecartEntity { @Override public void updateDefaultBlockMetadata() { - dirtyMetadata.put(EntityDataTypes.DISPLAY_BLOCK_STATE, session.getBlockMappings().getBedrockBlock(FurnaceBlock.state(hasFuel))); + BlockState furnace = Blocks.FURNACE.defaultBlockState().withValue(Properties.LIT, hasFuel); + dirtyMetadata.put(EntityDataTypes.DISPLAY_BLOCK_STATE, session.getBlockMappings().getBedrockBlock(furnace)); dirtyMetadata.put(EntityDataTypes.DISPLAY_OFFSET, 6); } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/SpawnerMinecartEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/SpawnerMinecartEntity.java index 65dfb800b..4d69c8a1e 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/SpawnerMinecartEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/SpawnerMinecartEntity.java @@ -28,7 +28,7 @@ package org.geysermc.geyser.entity.type; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.geysermc.geyser.entity.EntityDefinition; -import org.geysermc.geyser.level.block.type.SpawnerBlock; +import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.session.GeyserSession; import java.util.UUID; @@ -41,7 +41,7 @@ public class SpawnerMinecartEntity extends DefaultBlockMinecartEntity { @Override public void updateDefaultBlockMetadata() { - dirtyMetadata.put(EntityDataTypes.DISPLAY_BLOCK_STATE, session.getBlockMappings().getBedrockBlock(SpawnerBlock.state())); + dirtyMetadata.put(EntityDataTypes.DISPLAY_BLOCK_STATE, session.getBlockMappings().getBedrockBlock(Blocks.SPAWNER.defaultBlockState())); dirtyMetadata.put(EntityDataTypes.DISPLAY_OFFSET, 6); } } 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 0a51d43ef..9c8e5de15 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 @@ -41,7 +41,6 @@ import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.inventory.InventoryTranslator; -import org.geysermc.geyser.util.BlockUtils; import org.geysermc.geyser.util.InventoryUtils; import java.util.Collections; @@ -56,22 +55,24 @@ public class BlockInventoryHolder extends InventoryHolder { /** * The default Java block ID to translate as a fake block */ - private final int defaultJavaBlockState; + private final BlockState defaultJavaBlockState; private final ContainerType containerType; - private final Set validBlocks; + private final Set validBlocks; - public BlockInventoryHolder(String javaBlockIdentifier, ContainerType containerType, Block... validBlocks) { - this.defaultJavaBlockState = BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getInt(javaBlockIdentifier); + public BlockInventoryHolder(Block defaultJavaBlock, ContainerType containerType, Block... validBlocks) { + this(defaultJavaBlock.defaultBlockState(), containerType, validBlocks); + } + + public BlockInventoryHolder(BlockState defaultJavaBlockState, ContainerType containerType, Block... validBlocks) { + this.defaultJavaBlockState = defaultJavaBlockState; this.containerType = containerType; if (validBlocks != null) { - Set validBlocksTemp = new HashSet<>(validBlocks.length + 1); - for (Block block : validBlocks) { - validBlocksTemp.add(block.javaIdentifier().toString()); - } - validBlocksTemp.add(BlockUtils.getCleanIdentifier(javaBlockIdentifier)); + Set validBlocksTemp = new HashSet<>(validBlocks.length + 1); + Collections.addAll(validBlocksTemp, validBlocks); + validBlocksTemp.add(defaultJavaBlockState.block()); this.validBlocks = Set.copyOf(validBlocksTemp); } else { - this.validBlocks = Collections.singleton(BlockUtils.getCleanIdentifier(javaBlockIdentifier)); + this.validBlocks = Collections.singleton(defaultJavaBlockState.block()); } } @@ -85,9 +86,7 @@ public class BlockInventoryHolder extends InventoryHolder { // and the bedrock block is vanilla BlockState state = session.getGeyser().getWorldManager().blockAt(session, session.getLastInteractionBlockPosition()); if (!BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get().containsKey(state.javaId())) { - // TODO TODO TODO - String[] javaBlockString = state.toString().split("\\["); - if (isValidBlock(javaBlockString)) { + if (isValidBlock(state)) { // We can safely use this block inventory.setHolderPosition(session.getLastInteractionBlockPosition()); ((Container) inventory).setUsingRealBlock(true, state.block()); @@ -111,7 +110,7 @@ public class BlockInventoryHolder extends InventoryHolder { session.sendUpstreamPacket(blockPacket); inventory.setHolderPosition(position); - setCustomName(session, position, inventory, BlockState.of(defaultJavaBlockState)); + setCustomName(session, position, inventory, defaultJavaBlockState); return true; } @@ -129,8 +128,8 @@ public class BlockInventoryHolder extends InventoryHolder { /** * @return true if this Java block ID can be used for player inventory. */ - protected boolean isValidBlock(String[] javaBlockString) { - return this.validBlocks.contains(javaBlockString[0]); + protected boolean isValidBlock(BlockState blockState) { + return this.validBlocks.contains(blockState.block()); } protected void setCustomName(GeyserSession session, Vector3i position, Inventory inventory, BlockState javaBlockState) { 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 d52c46e33..01e95fc7a 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 @@ -25,17 +25,10 @@ package org.geysermc.geyser.level.block; -import it.unimi.dsi.fastutil.ints.Int2IntMap; -import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; -import it.unimi.dsi.fastutil.ints.IntOpenHashSet; -import it.unimi.dsi.fastutil.ints.IntSet; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.level.block.type.PistonBlock; -import org.geysermc.geyser.level.physics.Direction; import org.geysermc.geyser.level.physics.PistonBehavior; import org.geysermc.geyser.registry.BlockRegistries; @@ -43,53 +36,8 @@ import org.geysermc.geyser.registry.BlockRegistries; * Used for block entities if the Java block state contains Bedrock block information. */ public final class BlockStateValues { - private static final Object2IntMap PISTON_HEADS = new Object2IntOpenHashMap<>(); - private static final IntSet ALL_PISTON_HEADS = new IntOpenHashSet(); - private static final Int2IntMap WATER_LEVEL = new Int2IntOpenHashMap(); - - public static int JAVA_WATER_ID; - public static final int NUM_WATER_LEVELS = 9; - /** - * Determines if the block state contains Bedrock block information - * - * @param javaId The Java Identifier of the block - * @param javaBlockState the Java Block State of the block - */ - public static void storeBlockStateValues(String javaId, int javaBlockState) { - if (javaId.contains("piston[")) { // minecraft:moving_piston, minecraft:sticky_piston, minecraft:piston - return; - } else if (javaId.startsWith("minecraft:piston_head")) { - ALL_PISTON_HEADS.add(javaBlockState); - if (javaId.contains("short=false")) { - PISTON_HEADS.put(getBlockDirection(javaId), javaBlockState); - } - return; - } - - if (javaId.startsWith("minecraft:water") && !javaId.contains("cauldron")) { - String strLevel = javaId.substring(javaId.lastIndexOf("level=") + 6, javaId.length() - 1); - int level = Integer.parseInt(strLevel); - WATER_LEVEL.put(javaBlockState, level); - } - } - - public static boolean isPistonHead(int state) { - return ALL_PISTON_HEADS.contains(state); - } - - /** - * Get the Java Block State for a piston head for a specific direction - * This is used in PistonBlockEntity to get the BlockCollision for the piston head. - * - * @param direction Direction the piston head points in - * @return Block state for the piston head - */ - public static int getPistonHead(Direction direction) { - return PISTON_HEADS.getOrDefault(direction, Block.JAVA_AIR_ID); - } - /** * Checks if a block sticks to other blocks * (Slime and honey blocks) @@ -158,7 +106,11 @@ public final class BlockStateValues { * @return The water level or -1 if the block isn't water */ public static int getWaterLevel(int state) { - return WATER_LEVEL.getOrDefault(state, -1); + BlockState blockState = BlockState.of(state); + if (!blockState.is(Blocks.WATER)) { + return -1; + } + return blockState.getValue(Properties.LEVEL); } /** @@ -206,23 +158,6 @@ public final class BlockStateValues { return 0.6f; } - private static Direction getBlockDirection(String javaId) { - if (javaId.contains("down")) { - return Direction.DOWN; - } else if (javaId.contains("up")) { - return Direction.UP; - } else if (javaId.contains("south")) { - return Direction.SOUTH; - } else if (javaId.contains("west")) { - return Direction.WEST; - } else if (javaId.contains("north")) { - return Direction.NORTH; - } else if (javaId.contains("east")) { - return Direction.EAST; - } - throw new IllegalStateException(); - } - private BlockStateValues() { } } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java index 283ca2503..fa605c079 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java @@ -65,36 +65,36 @@ public final class Blocks { public static final Block BAMBOO_PLANKS = register(new Block("bamboo_planks", builder().destroyTime(2.0f))); public static final Block BAMBOO_MOSAIC = register(new Block("bamboo_mosaic", builder().destroyTime(2.0f))); public static final Block OAK_SAPLING = register(new Block("oak_sapling", builder().pushReaction(PistonBehavior.DESTROY) - .intState(STAGE, 0, 1))); + .intState(STAGE))); public static final Block SPRUCE_SAPLING = register(new Block("spruce_sapling", builder().pushReaction(PistonBehavior.DESTROY) - .intState(STAGE, 0, 1))); + .intState(STAGE))); public static final Block BIRCH_SAPLING = register(new Block("birch_sapling", builder().pushReaction(PistonBehavior.DESTROY) - .intState(STAGE, 0, 1))); + .intState(STAGE))); public static final Block JUNGLE_SAPLING = register(new Block("jungle_sapling", builder().pushReaction(PistonBehavior.DESTROY) - .intState(STAGE, 0, 1))); + .intState(STAGE))); public static final Block ACACIA_SAPLING = register(new Block("acacia_sapling", builder().pushReaction(PistonBehavior.DESTROY) - .intState(STAGE, 0, 1))); + .intState(STAGE))); public static final Block CHERRY_SAPLING = register(new Block("cherry_sapling", builder().pushReaction(PistonBehavior.DESTROY) - .intState(STAGE, 0, 1))); + .intState(STAGE))); public static final Block DARK_OAK_SAPLING = register(new Block("dark_oak_sapling", builder().pushReaction(PistonBehavior.DESTROY) - .intState(STAGE, 0, 1))); + .intState(STAGE))); public static final Block MANGROVE_PROPAGULE = register(new Block("mangrove_propagule", builder().pushReaction(PistonBehavior.DESTROY) - .intState(AGE_4, 0, 4) + .intState(AGE_4) .booleanState(HANGING) - .intState(STAGE, 0, 1) + .intState(STAGE) .booleanState(WATERLOGGED))); public static final Block BEDROCK = register(new Block("bedrock", builder().destroyTime(-1.0f))); public static final Block WATER = register(new WaterBlock("water", builder().destroyTime(100.0f).pushReaction(PistonBehavior.DESTROY) - .intState(LEVEL, 0, 15))); + .intState(LEVEL))); public static final Block LAVA = register(new Block("lava", builder().destroyTime(100.0f).pushReaction(PistonBehavior.DESTROY) - .intState(LEVEL, 0, 15))); + .intState(LEVEL))); public static final Block SAND = register(new Block("sand", builder().destroyTime(0.5f))); public static final Block SUSPICIOUS_SAND = register(new Block("suspicious_sand", builder().setBlockEntity().destroyTime(0.25f).pushReaction(PistonBehavior.DESTROY) - .intState(DUSTED, 0, 3))); + .intState(DUSTED))); public static final Block RED_SAND = register(new Block("red_sand", builder().destroyTime(0.5f))); public static final Block GRAVEL = register(new Block("gravel", builder().destroyTime(0.6f))); public static final Block SUSPICIOUS_GRAVEL = register(new Block("suspicious_gravel", builder().setBlockEntity().destroyTime(0.25f).pushReaction(PistonBehavior.DESTROY) - .intState(DUSTED, 0, 3))); + .intState(DUSTED))); public static final Block GOLD_ORE = register(new Block("gold_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); public static final Block DEEPSLATE_GOLD_ORE = register(new Block("deepslate_gold_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f))); public static final Block IRON_ORE = register(new Block("iron_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); @@ -175,43 +175,43 @@ public final class Blocks { public static final Block STRIPPED_MANGROVE_WOOD = register(new Block("stripped_mangrove_wood", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); public static final Block OAK_LEAVES = register(new Block("oak_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) - .intState(DISTANCE, 1, 7) + .intState(DISTANCE) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); public static final Block SPRUCE_LEAVES = register(new Block("spruce_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) - .intState(DISTANCE, 1, 7) + .intState(DISTANCE) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); public static final Block BIRCH_LEAVES = register(new Block("birch_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) - .intState(DISTANCE, 1, 7) + .intState(DISTANCE) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); public static final Block JUNGLE_LEAVES = register(new Block("jungle_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) - .intState(DISTANCE, 1, 7) + .intState(DISTANCE) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); public static final Block ACACIA_LEAVES = register(new Block("acacia_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) - .intState(DISTANCE, 1, 7) + .intState(DISTANCE) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); public static final Block CHERRY_LEAVES = register(new Block("cherry_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) - .intState(DISTANCE, 1, 7) + .intState(DISTANCE) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); public static final Block DARK_OAK_LEAVES = register(new Block("dark_oak_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) - .intState(DISTANCE, 1, 7) + .intState(DISTANCE) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); public static final Block MANGROVE_LEAVES = register(new Block("mangrove_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) - .intState(DISTANCE, 1, 7) + .intState(DISTANCE) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); public static final Block AZALEA_LEAVES = register(new Block("azalea_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) - .intState(DISTANCE, 1, 7) + .intState(DISTANCE) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); public static final Block FLOWERING_AZALEA_LEAVES = register(new Block("flowering_azalea_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) - .intState(DISTANCE, 1, 7) + .intState(DISTANCE) .booleanState(PERSISTENT) .booleanState(WATERLOGGED))); public static final Block SPONGE = register(new Block("sponge", builder().destroyTime(0.6f))); @@ -227,80 +227,80 @@ public final class Blocks { public static final Block CHISELED_SANDSTONE = register(new Block("chiseled_sandstone", builder().requiresCorrectToolForDrops().destroyTime(0.8f))); public static final Block CUT_SANDSTONE = register(new Block("cut_sandstone", builder().requiresCorrectToolForDrops().destroyTime(0.8f))); public static final Block NOTE_BLOCK = register(new Block("note_block", builder().destroyTime(0.8f) - .enumState(NOTEBLOCK_INSTRUMENT, "harp", "basedrum", "snare", "hat", "bass", "flute", "bell", "guitar", "chime", "xylophone", "iron_xylophone", "cow_bell", "didgeridoo", "bit", "banjo", "pling", "zombie", "skeleton", "creeper", "dragon", "wither_skeleton", "piglin", "custom_head") - .intState(NOTE, 0, 24) + .enumState(NOTEBLOCK_INSTRUMENT) + .intState(NOTE) .booleanState(POWERED))); public static final Block WHITE_BED = register(new BedBlock("white_bed", 0, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) - .enumState(BED_PART, "head", "foot"))); + .enumState(BED_PART))); public static final Block ORANGE_BED = register(new BedBlock("orange_bed", 1, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) - .enumState(BED_PART, "head", "foot"))); + .enumState(BED_PART))); public static final Block MAGENTA_BED = register(new BedBlock("magenta_bed", 2, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) - .enumState(BED_PART, "head", "foot"))); + .enumState(BED_PART))); public static final Block LIGHT_BLUE_BED = register(new BedBlock("light_blue_bed", 3, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) - .enumState(BED_PART, "head", "foot"))); + .enumState(BED_PART))); public static final Block YELLOW_BED = register(new BedBlock("yellow_bed", 4, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) - .enumState(BED_PART, "head", "foot"))); + .enumState(BED_PART))); public static final Block LIME_BED = register(new BedBlock("lime_bed", 5, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) - .enumState(BED_PART, "head", "foot"))); + .enumState(BED_PART))); public static final Block PINK_BED = register(new BedBlock("pink_bed", 6, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) - .enumState(BED_PART, "head", "foot"))); + .enumState(BED_PART))); public static final Block GRAY_BED = register(new BedBlock("gray_bed", 7, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) - .enumState(BED_PART, "head", "foot"))); + .enumState(BED_PART))); public static final Block LIGHT_GRAY_BED = register(new BedBlock("light_gray_bed", 8, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) - .enumState(BED_PART, "head", "foot"))); + .enumState(BED_PART))); public static final Block CYAN_BED = register(new BedBlock("cyan_bed", 9, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) - .enumState(BED_PART, "head", "foot"))); + .enumState(BED_PART))); public static final Block PURPLE_BED = register(new BedBlock("purple_bed", 10, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) - .enumState(BED_PART, "head", "foot"))); + .enumState(BED_PART))); public static final Block BLUE_BED = register(new BedBlock("blue_bed", 11, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) - .enumState(BED_PART, "head", "foot"))); + .enumState(BED_PART))); public static final Block BROWN_BED = register(new BedBlock("brown_bed", 12, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) - .enumState(BED_PART, "head", "foot"))); + .enumState(BED_PART))); public static final Block GREEN_BED = register(new BedBlock("green_bed", 13, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) - .enumState(BED_PART, "head", "foot"))); + .enumState(BED_PART))); public static final Block RED_BED = register(new BedBlock("red_bed", 14, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) - .enumState(BED_PART, "head", "foot"))); + .enumState(BED_PART))); public static final Block BLACK_BED = register(new BedBlock("black_bed", 15, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) - .enumState(BED_PART, "head", "foot"))); + .enumState(BED_PART))); public static final Block POWERED_RAIL = register(new Block("powered_rail", builder().destroyTime(0.7f) .booleanState(POWERED) - .enumState(RAIL_SHAPE_STRAIGHT, "north_south", "east_west", "ascending_east", "ascending_west", "ascending_north", "ascending_south") + .enumState(RAIL_SHAPE_STRAIGHT) .booleanState(WATERLOGGED))); public static final Block DETECTOR_RAIL = register(new Block("detector_rail", builder().destroyTime(0.7f) .booleanState(POWERED) - .enumState(RAIL_SHAPE_STRAIGHT, "north_south", "east_west", "ascending_east", "ascending_west", "ascending_north", "ascending_south") + .enumState(RAIL_SHAPE_STRAIGHT) .booleanState(WATERLOGGED))); public static final Block STICKY_PISTON = register(new PistonBlock("sticky_piston", builder().destroyTime(1.5f).pushReaction(PistonBehavior.BLOCK) .booleanState(EXTENDED) @@ -311,14 +311,14 @@ public final class Blocks { public static final Block DEAD_BUSH = register(new Block("dead_bush", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block SEAGRASS = register(new Block("seagrass", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block TALL_SEAGRASS = register(new Block("tall_seagrass", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.SEAGRASS) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); + .enumState(DOUBLE_BLOCK_HALF))); public static final Block PISTON = register(new PistonBlock("piston", builder().destroyTime(1.5f).pushReaction(PistonBehavior.BLOCK) .booleanState(EXTENDED) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); public static final Block PISTON_HEAD = register(new Block("piston_head", builder().destroyTime(1.5f).pushReaction(PistonBehavior.BLOCK) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .booleanState(SHORT) - .enumState(PISTON_TYPE, "normal", "sticky"))); + .enumState(PISTON_TYPE))); public static final Block WHITE_WOOL = register(new Block("white_wool", builder().destroyTime(0.8f))); public static final Block ORANGE_WOOL = register(new Block("orange_wool", builder().destroyTime(0.8f))); public static final Block MAGENTA_WOOL = register(new Block("magenta_wool", builder().destroyTime(0.8f))); @@ -337,7 +337,7 @@ public final class Blocks { public static final Block BLACK_WOOL = register(new Block("black_wool", builder().destroyTime(0.8f))); public static final Block MOVING_PISTON = register(new MovingPistonBlock("moving_piston", builder().setBlockEntity().destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) - .enumState(PISTON_TYPE, "normal", "sticky"))); + .enumState(PISTON_TYPE))); public static final Block DANDELION = register(new Block("dandelion", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block TORCHFLOWER = register(new Block("torchflower", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block POPPY = register(new Block("poppy", builder().pushReaction(PistonBehavior.DESTROY))); @@ -374,7 +374,7 @@ public final class Blocks { public static final Block WALL_TORCH = register(new Block("wall_torch", builder().pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); public static final Block FIRE = register(new Block("fire", builder().pushReaction(PistonBehavior.DESTROY) - .intState(AGE_15, 0, 15) + .intState(AGE_15) .booleanState(EAST) .booleanState(NORTH) .booleanState(SOUTH) @@ -384,73 +384,73 @@ public final class Blocks { public static final Block SPAWNER = register(new SpawnerBlock("spawner", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(5.0f))); public static final Block OAK_STAIRS = register(new Block("oak_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block CHEST = register(new ChestBlock("chest", builder().setBlockEntity().destroyTime(2.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(CHEST_TYPE, ChestType.VALUES) .booleanState(WATERLOGGED))); public static final Block REDSTONE_WIRE = register(new Block("redstone_wire", builder().pushReaction(PistonBehavior.DESTROY) - .enumState(EAST_REDSTONE, "up", "side", "none") - .enumState(NORTH_REDSTONE, "up", "side", "none") - .intState(POWER, 0, 15) - .enumState(SOUTH_REDSTONE, "up", "side", "none") - .enumState(WEST_REDSTONE, "up", "side", "none"))); + .enumState(EAST_REDSTONE) + .enumState(NORTH_REDSTONE) + .intState(POWER) + .enumState(SOUTH_REDSTONE) + .enumState(WEST_REDSTONE))); public static final Block DIAMOND_ORE = register(new Block("diamond_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); public static final Block DEEPSLATE_DIAMOND_ORE = register(new Block("deepslate_diamond_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f))); public static final Block DIAMOND_BLOCK = register(new Block("diamond_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f))); public static final Block CRAFTING_TABLE = register(new Block("crafting_table", builder().destroyTime(2.5f))); public static final Block WHEAT = register(new Block("wheat", builder().pushReaction(PistonBehavior.DESTROY) - .intState(AGE_7, 0, 7))); + .intState(AGE_7))); public static final Block FARMLAND = register(new Block("farmland", builder().destroyTime(0.6f) - .intState(MOISTURE, 0, 7))); + .intState(MOISTURE))); public static final Block FURNACE = register(new FurnaceBlock("furnace", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(LIT))); public static final Block OAK_SIGN = register(new Block("oak_sign", builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15) + .intState(ROTATION_16) .booleanState(WATERLOGGED))); public static final Block SPRUCE_SIGN = register(new Block("spruce_sign", builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15) + .intState(ROTATION_16) .booleanState(WATERLOGGED))); public static final Block BIRCH_SIGN = register(new Block("birch_sign", builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15) + .intState(ROTATION_16) .booleanState(WATERLOGGED))); public static final Block ACACIA_SIGN = register(new Block("acacia_sign", builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15) + .intState(ROTATION_16) .booleanState(WATERLOGGED))); public static final Block CHERRY_SIGN = register(new Block("cherry_sign", builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15) + .intState(ROTATION_16) .booleanState(WATERLOGGED))); public static final Block JUNGLE_SIGN = register(new Block("jungle_sign", builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15) + .intState(ROTATION_16) .booleanState(WATERLOGGED))); public static final Block DARK_OAK_SIGN = register(new Block("dark_oak_sign", builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15) + .intState(ROTATION_16) .booleanState(WATERLOGGED))); public static final Block MANGROVE_SIGN = register(new Block("mangrove_sign", builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15) + .intState(ROTATION_16) .booleanState(WATERLOGGED))); public static final Block BAMBOO_SIGN = register(new Block("bamboo_sign", builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15) + .intState(ROTATION_16) .booleanState(WATERLOGGED))); public static final Block OAK_DOOR = register(new DoorBlock("oak_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") - .enumState(DOOR_HINGE, "left", "right") + .enumState(DOUBLE_BLOCK_HALF) + .enumState(DOOR_HINGE) .booleanState(OPEN) .booleanState(POWERED))); public static final Block LADDER = register(new Block("ladder", builder().destroyTime(0.4f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); public static final Block RAIL = register(new Block("rail", builder().destroyTime(0.7f) - .enumState(RAIL_SHAPE, "north_south", "east_west", "ascending_east", "ascending_west", "ascending_north", "ascending_south", "south_east", "south_west", "north_west", "north_east") + .enumState(RAIL_SHAPE) .booleanState(WATERLOGGED))); public static final Block COBBLESTONE_STAIRS = register(new Block("cobblestone_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block OAK_WALL_SIGN = register(new Block("oak_wall_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) @@ -481,47 +481,47 @@ public final class Blocks { .booleanState(WATERLOGGED))); public static final Block OAK_HANGING_SIGN = register(new Block("oak_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .booleanState(ATTACHED) - .intState(ROTATION_16, 0, 15) + .intState(ROTATION_16) .booleanState(WATERLOGGED))); public static final Block SPRUCE_HANGING_SIGN = register(new Block("spruce_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .booleanState(ATTACHED) - .intState(ROTATION_16, 0, 15) + .intState(ROTATION_16) .booleanState(WATERLOGGED))); public static final Block BIRCH_HANGING_SIGN = register(new Block("birch_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .booleanState(ATTACHED) - .intState(ROTATION_16, 0, 15) + .intState(ROTATION_16) .booleanState(WATERLOGGED))); public static final Block ACACIA_HANGING_SIGN = register(new Block("acacia_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .booleanState(ATTACHED) - .intState(ROTATION_16, 0, 15) + .intState(ROTATION_16) .booleanState(WATERLOGGED))); public static final Block CHERRY_HANGING_SIGN = register(new Block("cherry_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .booleanState(ATTACHED) - .intState(ROTATION_16, 0, 15) + .intState(ROTATION_16) .booleanState(WATERLOGGED))); public static final Block JUNGLE_HANGING_SIGN = register(new Block("jungle_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .booleanState(ATTACHED) - .intState(ROTATION_16, 0, 15) + .intState(ROTATION_16) .booleanState(WATERLOGGED))); public static final Block DARK_OAK_HANGING_SIGN = register(new Block("dark_oak_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .booleanState(ATTACHED) - .intState(ROTATION_16, 0, 15) + .intState(ROTATION_16) .booleanState(WATERLOGGED))); public static final Block CRIMSON_HANGING_SIGN = register(new Block("crimson_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .booleanState(ATTACHED) - .intState(ROTATION_16, 0, 15) + .intState(ROTATION_16) .booleanState(WATERLOGGED))); public static final Block WARPED_HANGING_SIGN = register(new Block("warped_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .booleanState(ATTACHED) - .intState(ROTATION_16, 0, 15) + .intState(ROTATION_16) .booleanState(WATERLOGGED))); public static final Block MANGROVE_HANGING_SIGN = register(new Block("mangrove_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .booleanState(ATTACHED) - .intState(ROTATION_16, 0, 15) + .intState(ROTATION_16) .booleanState(WATERLOGGED))); public static final Block BAMBOO_HANGING_SIGN = register(new Block("bamboo_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .booleanState(ATTACHED) - .intState(ROTATION_16, 0, 15) + .intState(ROTATION_16) .booleanState(WATERLOGGED))); public static final Block OAK_WALL_HANGING_SIGN = register(new Block("oak_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) @@ -557,15 +557,15 @@ public final class Blocks { .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); public static final Block LEVER = register(new Block("lever", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) - .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); public static final Block STONE_PRESSURE_PLATE = register(new Block("stone_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED))); public static final Block IRON_DOOR = register(new DoorBlock("iron_door", builder().requiresCorrectToolForDrops().destroyTime(5.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") - .enumState(DOOR_HINGE, "left", "right") + .enumState(DOUBLE_BLOCK_HALF) + .enumState(DOOR_HINGE) .booleanState(OPEN) .booleanState(POWERED))); public static final Block OAK_PRESSURE_PLATE = register(new Block("oak_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) @@ -596,18 +596,18 @@ public final class Blocks { .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(LIT))); public static final Block STONE_BUTTON = register(new Block("stone_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) - .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); public static final Block SNOW = register(new Block("snow", builder().requiresCorrectToolForDrops().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) - .intState(LAYERS, 1, 8))); + .intState(LAYERS))); public static final Block ICE = register(new Block("ice", builder().destroyTime(0.5f))); public static final Block SNOW_BLOCK = register(new Block("snow_block", builder().requiresCorrectToolForDrops().destroyTime(0.2f))); public static final Block CACTUS = register(new Block("cactus", builder().destroyTime(0.4f).pushReaction(PistonBehavior.DESTROY) - .intState(AGE_15, 0, 15))); + .intState(AGE_15))); public static final Block CLAY = register(new Block("clay", builder().destroyTime(0.6f))); public static final Block SUGAR_CANE = register(new Block("sugar_cane", builder().pushReaction(PistonBehavior.DESTROY) - .intState(AGE_15, 0, 15))); + .intState(AGE_15))); public static final Block JUKEBOX = register(new Block("jukebox", builder().setBlockEntity().destroyTime(2.0f) .booleanState(HAS_RECORD))); public static final Block OAK_FENCE = register(new Block("oak_fence", builder().destroyTime(2.0f) @@ -634,9 +634,9 @@ public final class Blocks { public static final Block JACK_O_LANTERN = register(new Block("jack_o_lantern", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); public static final Block CAKE = register(new Block("cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) - .intState(BITES, 0, 6))); + .intState(BITES))); public static final Block REPEATER = register(new Block("repeater", builder().pushReaction(PistonBehavior.DESTROY) - .intState(DELAY, 1, 4) + .intState(DELAY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(LOCKED) .booleanState(POWERED))); @@ -658,55 +658,55 @@ public final class Blocks { public static final Block BLACK_STAINED_GLASS = register(new Block("black_stained_glass", builder().destroyTime(0.3f))); public static final Block OAK_TRAPDOOR = register(new TrapDoorBlock("oak_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") + .enumState(HALF) .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); public static final Block SPRUCE_TRAPDOOR = register(new TrapDoorBlock("spruce_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") + .enumState(HALF) .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); public static final Block BIRCH_TRAPDOOR = register(new TrapDoorBlock("birch_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") + .enumState(HALF) .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); public static final Block JUNGLE_TRAPDOOR = register(new TrapDoorBlock("jungle_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") + .enumState(HALF) .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); public static final Block ACACIA_TRAPDOOR = register(new TrapDoorBlock("acacia_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") + .enumState(HALF) .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); public static final Block CHERRY_TRAPDOOR = register(new TrapDoorBlock("cherry_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") + .enumState(HALF) .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); public static final Block DARK_OAK_TRAPDOOR = register(new TrapDoorBlock("dark_oak_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") + .enumState(HALF) .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); public static final Block MANGROVE_TRAPDOOR = register(new TrapDoorBlock("mangrove_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") + .enumState(HALF) .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); public static final Block BAMBOO_TRAPDOOR = register(new TrapDoorBlock("bamboo_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") + .enumState(HALF) .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); @@ -765,9 +765,9 @@ public final class Blocks { public static final Block ATTACHED_MELON_STEM = register(new Block("attached_melon_stem", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.MELON_SEEDS) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); public static final Block PUMPKIN_STEM = register(new Block("pumpkin_stem", builder().pushReaction(PistonBehavior.DESTROY) - .intState(AGE_7, 0, 7))); + .intState(AGE_7))); public static final Block MELON_STEM = register(new Block("melon_stem", builder().pushReaction(PistonBehavior.DESTROY) - .intState(AGE_7, 0, 7))); + .intState(AGE_7))); public static final Block VINE = register(new Block("vine", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .booleanState(EAST) .booleanState(NORTH) @@ -789,18 +789,18 @@ public final class Blocks { .booleanState(POWERED))); public static final Block BRICK_STAIRS = register(new Block("brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block STONE_BRICK_STAIRS = register(new Block("stone_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block MUD_BRICK_STAIRS = register(new Block("mud_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block MYCELIUM = register(new Block("mycelium", builder().destroyTime(0.6f) .booleanState(SNOWY))); @@ -814,11 +814,11 @@ public final class Blocks { .booleanState(WEST))); public static final Block NETHER_BRICK_STAIRS = register(new Block("nether_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block NETHER_WART = register(new Block("nether_wart", builder().pushReaction(PistonBehavior.DESTROY) - .intState(AGE_3, 0, 3))); + .intState(AGE_3))); public static final Block ENCHANTING_TABLE = register(new Block("enchanting_table", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(5.0f))); public static final Block BREWING_STAND = register(new Block("brewing_stand", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(0.5f) .booleanState(HAS_BOTTLE_0) @@ -826,10 +826,10 @@ public final class Blocks { .booleanState(HAS_BOTTLE_2))); public static final Block CAULDRON = register(new CauldronBlock("cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); public static final Block WATER_CAULDRON = register(new CauldronBlock("water_cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .intState(LEVEL_CAULDRON, 1, 3))); + .intState(LEVEL_CAULDRON))); public static final Block LAVA_CAULDRON = register(new CauldronBlock("lava_cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); public static final Block POWDER_SNOW_CAULDRON = register(new CauldronBlock("powder_snow_cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .intState(LEVEL_CAULDRON, 1, 3))); + .intState(LEVEL_CAULDRON))); public static final Block END_PORTAL = register(new Block("end_portal", builder().setBlockEntity().destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK))); public static final Block END_PORTAL_FRAME = register(new Block("end_portal_frame", builder().destroyTime(-1.0f) .booleanState(EYE) @@ -839,12 +839,12 @@ public final class Blocks { public static final Block REDSTONE_LAMP = register(new Block("redstone_lamp", builder().destroyTime(0.3f) .booleanState(LIT))); public static final Block COCOA = register(new Block("cocoa", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) - .intState(AGE_2, 0, 2) + .intState(AGE_2) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); public static final Block SANDSTONE_STAIRS = register(new Block("sandstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(0.8f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block EMERALD_ORE = register(new Block("emerald_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); public static final Block DEEPSLATE_EMERALD_ORE = register(new Block("deepslate_emerald_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f))); @@ -866,37 +866,37 @@ public final class Blocks { public static final Block EMERALD_BLOCK = register(new Block("emerald_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f))); public static final Block SPRUCE_STAIRS = register(new Block("spruce_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block BIRCH_STAIRS = register(new Block("birch_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block JUNGLE_STAIRS = register(new Block("jungle_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block COMMAND_BLOCK = register(new Block("command_block", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(-1.0f) .booleanState(CONDITIONAL) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); public static final Block BEACON = register(new Block("beacon", builder().setBlockEntity().destroyTime(3.0f))); public static final Block COBBLESTONE_WALL = register(new Block("cobblestone_wall", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(EAST_WALL, "none", "low", "tall") - .enumState(NORTH_WALL, "none", "low", "tall") - .enumState(SOUTH_WALL, "none", "low", "tall") + .enumState(EAST_WALL) + .enumState(NORTH_WALL) + .enumState(SOUTH_WALL) .booleanState(UP) .booleanState(WATERLOGGED) - .enumState(WEST_WALL, "none", "low", "tall"))); + .enumState(WEST_WALL))); public static final Block MOSSY_COBBLESTONE_WALL = register(new Block("mossy_cobblestone_wall", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(EAST_WALL, "none", "low", "tall") - .enumState(NORTH_WALL, "none", "low", "tall") - .enumState(SOUTH_WALL, "none", "low", "tall") + .enumState(EAST_WALL) + .enumState(NORTH_WALL) + .enumState(SOUTH_WALL) .booleanState(UP) .booleanState(WATERLOGGED) - .enumState(WEST_WALL, "none", "low", "tall"))); + .enumState(WEST_WALL))); public static final Block FLOWER_POT = register(new FlowerPotBlock("flower_pot", AIR, builder().pushReaction(PistonBehavior.DESTROY))); public static final Block POTTED_TORCHFLOWER = register(new FlowerPotBlock("potted_torchflower", TORCHFLOWER, builder().pushReaction(PistonBehavior.DESTROY))); public static final Block POTTED_OAK_SAPLING = register(new FlowerPotBlock("potted_oak_sapling", OAK_SAPLING, builder().pushReaction(PistonBehavior.DESTROY))); @@ -926,84 +926,84 @@ public final class Blocks { public static final Block POTTED_DEAD_BUSH = register(new FlowerPotBlock("potted_dead_bush", DEAD_BUSH, builder().pushReaction(PistonBehavior.DESTROY))); public static final Block POTTED_CACTUS = register(new FlowerPotBlock("potted_cactus", CACTUS, builder().pushReaction(PistonBehavior.DESTROY))); public static final Block CARROTS = register(new Block("carrots", builder().pushReaction(PistonBehavior.DESTROY) - .intState(AGE_7, 0, 7))); + .intState(AGE_7))); public static final Block POTATOES = register(new Block("potatoes", builder().pushReaction(PistonBehavior.DESTROY) - .intState(AGE_7, 0, 7))); + .intState(AGE_7))); public static final Block OAK_BUTTON = register(new Block("oak_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) - .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); public static final Block SPRUCE_BUTTON = register(new Block("spruce_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) - .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); public static final Block BIRCH_BUTTON = register(new Block("birch_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) - .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); public static final Block JUNGLE_BUTTON = register(new Block("jungle_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) - .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); public static final Block ACACIA_BUTTON = register(new Block("acacia_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) - .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); public static final Block CHERRY_BUTTON = register(new Block("cherry_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) - .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); public static final Block DARK_OAK_BUTTON = register(new Block("dark_oak_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) - .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); public static final Block MANGROVE_BUTTON = register(new Block("mangrove_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) - .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); public static final Block BAMBOO_BUTTON = register(new Block("bamboo_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) - .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); public static final Block SKELETON_SKULL = register(new SkullBlock("skeleton_skull", SkullBlock.Type.SKELETON, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) - .intState(ROTATION_16, 0, 15))); + .intState(ROTATION_16))); public static final Block SKELETON_WALL_SKULL = register(new WallSkullBlock("skeleton_wall_skull", SkullBlock.Type.SKELETON, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); public static final Block WITHER_SKELETON_SKULL = register(new SkullBlock("wither_skeleton_skull", SkullBlock.Type.WITHER_SKELETON, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) - .intState(ROTATION_16, 0, 15))); + .intState(ROTATION_16))); public static final Block WITHER_SKELETON_WALL_SKULL = register(new WallSkullBlock("wither_skeleton_wall_skull", SkullBlock.Type.WITHER_SKELETON, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); public static final Block ZOMBIE_HEAD = register(new SkullBlock("zombie_head", SkullBlock.Type.ZOMBIE, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) - .intState(ROTATION_16, 0, 15))); + .intState(ROTATION_16))); public static final Block ZOMBIE_WALL_HEAD = register(new WallSkullBlock("zombie_wall_head", SkullBlock.Type.ZOMBIE, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); public static final Block PLAYER_HEAD = register(new SkullBlock("player_head", SkullBlock.Type.PLAYER, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) - .intState(ROTATION_16, 0, 15))); + .intState(ROTATION_16))); public static final Block PLAYER_WALL_HEAD = register(new WallSkullBlock("player_wall_head", SkullBlock.Type.PLAYER, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); public static final Block CREEPER_HEAD = register(new SkullBlock("creeper_head", SkullBlock.Type.CREEPER, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) - .intState(ROTATION_16, 0, 15))); + .intState(ROTATION_16))); public static final Block CREEPER_WALL_HEAD = register(new WallSkullBlock("creeper_wall_head", SkullBlock.Type.CREEPER, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); public static final Block DRAGON_HEAD = register(new SkullBlock("dragon_head", SkullBlock.Type.DRAGON, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) - .intState(ROTATION_16, 0, 15))); + .intState(ROTATION_16))); public static final Block DRAGON_WALL_HEAD = register(new WallSkullBlock("dragon_wall_head", SkullBlock.Type.DRAGON, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); public static final Block PIGLIN_HEAD = register(new SkullBlock("piglin_head", SkullBlock.Type.PIGLIN, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) - .intState(ROTATION_16, 0, 15))); + .intState(ROTATION_16))); public static final Block PIGLIN_WALL_HEAD = register(new WallSkullBlock("piglin_wall_head", SkullBlock.Type.PIGLIN, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); @@ -1018,16 +1018,16 @@ public final class Blocks { .enumState(CHEST_TYPE, ChestType.VALUES) .booleanState(WATERLOGGED))); public static final Block LIGHT_WEIGHTED_PRESSURE_PLATE = register(new Block("light_weighted_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) - .intState(POWER, 0, 15))); + .intState(POWER))); public static final Block HEAVY_WEIGHTED_PRESSURE_PLATE = register(new Block("heavy_weighted_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) - .intState(POWER, 0, 15))); + .intState(POWER))); public static final Block COMPARATOR = register(new Block("comparator", builder().setBlockEntity().pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(MODE_COMPARATOR, "compare", "subtract") + .enumState(MODE_COMPARATOR) .booleanState(POWERED))); public static final Block DAYLIGHT_DETECTOR = register(new Block("daylight_detector", builder().setBlockEntity().destroyTime(0.2f) .booleanState(INVERTED) - .intState(POWER, 0, 15))); + .intState(POWER))); public static final Block REDSTONE_BLOCK = register(new Block("redstone_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f))); public static final Block NETHER_QUARTZ_ORE = register(new Block("nether_quartz_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); public static final Block HOPPER = register(new Block("hopper", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(3.0f) @@ -1039,12 +1039,12 @@ public final class Blocks { .enumState(AXIS, Axis.VALUES))); public static final Block QUARTZ_STAIRS = register(new Block("quartz_stairs", builder().requiresCorrectToolForDrops().destroyTime(0.8f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block ACTIVATOR_RAIL = register(new Block("activator_rail", builder().destroyTime(0.7f) .booleanState(POWERED) - .enumState(RAIL_SHAPE_STRAIGHT, "north_south", "east_west", "ascending_east", "ascending_west", "ascending_north", "ascending_south") + .enumState(RAIL_SHAPE_STRAIGHT) .booleanState(WATERLOGGED))); public static final Block DROPPER = register(new Block("dropper", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) @@ -1163,43 +1163,43 @@ public final class Blocks { .booleanState(WEST))); public static final Block ACACIA_STAIRS = register(new Block("acacia_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block CHERRY_STAIRS = register(new Block("cherry_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block DARK_OAK_STAIRS = register(new Block("dark_oak_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block MANGROVE_STAIRS = register(new Block("mangrove_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block BAMBOO_STAIRS = register(new Block("bamboo_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block BAMBOO_MOSAIC_STAIRS = register(new Block("bamboo_mosaic_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block SLIME_BLOCK = register(new Block("slime_block", builder())); public static final Block BARRIER = register(new Block("barrier", builder().destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK) .booleanState(WATERLOGGED))); public static final Block LIGHT = register(new Block("light", builder().destroyTime(-1.0f) - .intState(LEVEL, 0, 15) + .intState(LEVEL) .booleanState(WATERLOGGED))); public static final Block IRON_TRAPDOOR = register(new TrapDoorBlock("iron_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(5.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") + .enumState(HALF) .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); @@ -1208,27 +1208,27 @@ public final class Blocks { public static final Block DARK_PRISMARINE = register(new Block("dark_prismarine", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); public static final Block PRISMARINE_STAIRS = register(new Block("prismarine_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block PRISMARINE_BRICK_STAIRS = register(new Block("prismarine_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block DARK_PRISMARINE_STAIRS = register(new Block("dark_prismarine_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block PRISMARINE_SLAB = register(new Block("prismarine_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block PRISMARINE_BRICK_SLAB = register(new Block("prismarine_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block DARK_PRISMARINE_SLAB = register(new Block("dark_prismarine_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block SEA_LANTERN = register(new Block("sea_lantern", builder().destroyTime(0.3f))); public static final Block HAY_BLOCK = register(new Block("hay_block", builder().destroyTime(0.5f) @@ -1253,49 +1253,49 @@ public final class Blocks { public static final Block COAL_BLOCK = register(new Block("coal_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f))); public static final Block PACKED_ICE = register(new Block("packed_ice", builder().destroyTime(0.5f))); public static final Block SUNFLOWER = register(new Block("sunflower", builder().pushReaction(PistonBehavior.DESTROY) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); + .enumState(DOUBLE_BLOCK_HALF))); public static final Block LILAC = register(new Block("lilac", builder().pushReaction(PistonBehavior.DESTROY) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); + .enumState(DOUBLE_BLOCK_HALF))); public static final Block ROSE_BUSH = register(new Block("rose_bush", builder().pushReaction(PistonBehavior.DESTROY) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); + .enumState(DOUBLE_BLOCK_HALF))); public static final Block PEONY = register(new Block("peony", builder().pushReaction(PistonBehavior.DESTROY) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); + .enumState(DOUBLE_BLOCK_HALF))); public static final Block TALL_GRASS = register(new Block("tall_grass", builder().pushReaction(PistonBehavior.DESTROY) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); + .enumState(DOUBLE_BLOCK_HALF))); public static final Block LARGE_FERN = register(new Block("large_fern", builder().pushReaction(PistonBehavior.DESTROY) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); + .enumState(DOUBLE_BLOCK_HALF))); public static final Block WHITE_BANNER = register(new BannerBlock("white_banner", 0, builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15))); + .intState(ROTATION_16))); public static final Block ORANGE_BANNER = register(new BannerBlock("orange_banner", 1, builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15))); + .intState(ROTATION_16))); public static final Block MAGENTA_BANNER = register(new BannerBlock("magenta_banner", 2, builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15))); + .intState(ROTATION_16))); public static final Block LIGHT_BLUE_BANNER = register(new BannerBlock("light_blue_banner", 3, builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15))); + .intState(ROTATION_16))); public static final Block YELLOW_BANNER = register(new BannerBlock("yellow_banner", 4, builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15))); + .intState(ROTATION_16))); public static final Block LIME_BANNER = register(new BannerBlock("lime_banner", 5, builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15))); + .intState(ROTATION_16))); public static final Block PINK_BANNER = register(new BannerBlock("pink_banner", 6, builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15))); + .intState(ROTATION_16))); public static final Block GRAY_BANNER = register(new BannerBlock("gray_banner", 7, builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15))); + .intState(ROTATION_16))); public static final Block LIGHT_GRAY_BANNER = register(new BannerBlock("light_gray_banner", 8, builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15))); + .intState(ROTATION_16))); public static final Block CYAN_BANNER = register(new BannerBlock("cyan_banner", 9, builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15))); + .intState(ROTATION_16))); public static final Block PURPLE_BANNER = register(new BannerBlock("purple_banner", 10, builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15))); + .intState(ROTATION_16))); public static final Block BLUE_BANNER = register(new BannerBlock("blue_banner", 11, builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15))); + .intState(ROTATION_16))); public static final Block BROWN_BANNER = register(new BannerBlock("brown_banner", 12, builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15))); + .intState(ROTATION_16))); public static final Block GREEN_BANNER = register(new BannerBlock("green_banner", 13, builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15))); + .intState(ROTATION_16))); public static final Block RED_BANNER = register(new BannerBlock("red_banner", 14, builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15))); + .intState(ROTATION_16))); public static final Block BLACK_BANNER = register(new BannerBlock("black_banner", 15, builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15))); + .intState(ROTATION_16))); public static final Block WHITE_WALL_BANNER = register(new BannerBlock("white_wall_banner", 0, builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); public static final Block ORANGE_WALL_BANNER = register(new BannerBlock("orange_wall_banner", 1, builder().setBlockEntity().destroyTime(1.0f) @@ -1333,80 +1333,80 @@ public final class Blocks { public static final Block CUT_RED_SANDSTONE = register(new Block("cut_red_sandstone", builder().requiresCorrectToolForDrops().destroyTime(0.8f))); public static final Block RED_SANDSTONE_STAIRS = register(new Block("red_sandstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(0.8f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block OAK_SLAB = register(new Block("oak_slab", builder().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block SPRUCE_SLAB = register(new Block("spruce_slab", builder().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block BIRCH_SLAB = register(new Block("birch_slab", builder().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block JUNGLE_SLAB = register(new Block("jungle_slab", builder().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block ACACIA_SLAB = register(new Block("acacia_slab", builder().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block CHERRY_SLAB = register(new Block("cherry_slab", builder().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block DARK_OAK_SLAB = register(new Block("dark_oak_slab", builder().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block MANGROVE_SLAB = register(new Block("mangrove_slab", builder().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block BAMBOO_SLAB = register(new Block("bamboo_slab", builder().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block BAMBOO_MOSAIC_SLAB = register(new Block("bamboo_mosaic_slab", builder().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block STONE_SLAB = register(new Block("stone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block SMOOTH_STONE_SLAB = register(new Block("smooth_stone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block SANDSTONE_SLAB = register(new Block("sandstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block CUT_SANDSTONE_SLAB = register(new Block("cut_sandstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block PETRIFIED_OAK_SLAB = register(new Block("petrified_oak_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block COBBLESTONE_SLAB = register(new Block("cobblestone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block BRICK_SLAB = register(new Block("brick_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block STONE_BRICK_SLAB = register(new Block("stone_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block MUD_BRICK_SLAB = register(new Block("mud_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block NETHER_BRICK_SLAB = register(new Block("nether_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block QUARTZ_SLAB = register(new Block("quartz_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block RED_SANDSTONE_SLAB = register(new Block("red_sandstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block CUT_RED_SANDSTONE_SLAB = register(new Block("cut_red_sandstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block PURPUR_SLAB = register(new Block("purpur_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block SMOOTH_STONE = register(new Block("smooth_stone", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); public static final Block SMOOTH_SANDSTONE = register(new Block("smooth_sandstone", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); @@ -1502,50 +1502,50 @@ public final class Blocks { .booleanState(WEST))); public static final Block SPRUCE_DOOR = register(new DoorBlock("spruce_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") - .enumState(DOOR_HINGE, "left", "right") + .enumState(DOUBLE_BLOCK_HALF) + .enumState(DOOR_HINGE) .booleanState(OPEN) .booleanState(POWERED))); public static final Block BIRCH_DOOR = register(new DoorBlock("birch_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") - .enumState(DOOR_HINGE, "left", "right") + .enumState(DOUBLE_BLOCK_HALF) + .enumState(DOOR_HINGE) .booleanState(OPEN) .booleanState(POWERED))); public static final Block JUNGLE_DOOR = register(new DoorBlock("jungle_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") - .enumState(DOOR_HINGE, "left", "right") + .enumState(DOUBLE_BLOCK_HALF) + .enumState(DOOR_HINGE) .booleanState(OPEN) .booleanState(POWERED))); public static final Block ACACIA_DOOR = register(new DoorBlock("acacia_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") - .enumState(DOOR_HINGE, "left", "right") + .enumState(DOUBLE_BLOCK_HALF) + .enumState(DOOR_HINGE) .booleanState(OPEN) .booleanState(POWERED))); public static final Block CHERRY_DOOR = register(new DoorBlock("cherry_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") - .enumState(DOOR_HINGE, "left", "right") + .enumState(DOUBLE_BLOCK_HALF) + .enumState(DOOR_HINGE) .booleanState(OPEN) .booleanState(POWERED))); public static final Block DARK_OAK_DOOR = register(new DoorBlock("dark_oak_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") - .enumState(DOOR_HINGE, "left", "right") + .enumState(DOUBLE_BLOCK_HALF) + .enumState(DOOR_HINGE) .booleanState(OPEN) .booleanState(POWERED))); public static final Block MANGROVE_DOOR = register(new DoorBlock("mangrove_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") - .enumState(DOOR_HINGE, "left", "right") + .enumState(DOUBLE_BLOCK_HALF) + .enumState(DOOR_HINGE) .booleanState(OPEN) .booleanState(POWERED))); public static final Block BAMBOO_DOOR = register(new DoorBlock("bamboo_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") - .enumState(DOOR_HINGE, "left", "right") + .enumState(DOUBLE_BLOCK_HALF) + .enumState(DOOR_HINGE) .booleanState(OPEN) .booleanState(POWERED))); public static final Block END_ROD = register(new Block("end_rod", builder() @@ -1558,25 +1558,25 @@ public final class Blocks { .booleanState(UP) .booleanState(WEST))); public static final Block CHORUS_FLOWER = register(new Block("chorus_flower", builder().destroyTime(0.4f).pushReaction(PistonBehavior.DESTROY) - .intState(AGE_5, 0, 5))); + .intState(AGE_5))); public static final Block PURPUR_BLOCK = register(new Block("purpur_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); public static final Block PURPUR_PILLAR = register(new Block("purpur_pillar", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(AXIS, Axis.VALUES))); public static final Block PURPUR_STAIRS = register(new Block("purpur_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block END_STONE_BRICKS = register(new Block("end_stone_bricks", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); public static final Block TORCHFLOWER_CROP = register(new Block("torchflower_crop", builder().pushReaction(PistonBehavior.DESTROY) - .intState(AGE_1, 0, 1))); + .intState(AGE_1))); public static final Block PITCHER_CROP = register(new Block("pitcher_crop", builder().pushReaction(PistonBehavior.DESTROY) - .intState(AGE_4, 0, 4) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); + .intState(AGE_4) + .enumState(DOUBLE_BLOCK_HALF))); public static final Block PITCHER_PLANT = register(new Block("pitcher_plant", builder().pushReaction(PistonBehavior.DESTROY) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower"))); + .enumState(DOUBLE_BLOCK_HALF))); public static final Block BEETROOTS = register(new Block("beetroots", builder().pushReaction(PistonBehavior.DESTROY) - .intState(AGE_3, 0, 3))); + .intState(AGE_3))); public static final Block DIRT_PATH = register(new Block("dirt_path", builder().destroyTime(0.65f))); public static final Block END_GATEWAY = register(new Block("end_gateway", builder().setBlockEntity().destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK))); public static final Block REPEATING_COMMAND_BLOCK = register(new Block("repeating_command_block", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(-1.0f) @@ -1586,7 +1586,7 @@ public final class Blocks { .booleanState(CONDITIONAL) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); public static final Block FROSTED_ICE = register(new Block("frosted_ice", builder().destroyTime(0.5f) - .intState(AGE_3, 0, 3))); + .intState(AGE_3))); public static final Block MAGMA_BLOCK = register(new Block("magma_block", builder().requiresCorrectToolForDrops().destroyTime(0.5f))); public static final Block NETHER_WART_BLOCK = register(new Block("nether_wart_block", builder().destroyTime(1.0f))); public static final Block RED_NETHER_BRICKS = register(new Block("red_nether_bricks", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); @@ -1695,14 +1695,14 @@ public final class Blocks { public static final Block RED_CONCRETE_POWDER = register(new Block("red_concrete_powder", builder().destroyTime(0.5f))); public static final Block BLACK_CONCRETE_POWDER = register(new Block("black_concrete_powder", builder().destroyTime(0.5f))); public static final Block KELP = register(new Block("kelp", builder().pushReaction(PistonBehavior.DESTROY) - .intState(AGE_25, 0, 25))); + .intState(AGE_25))); public static final Block KELP_PLANT = register(new Block("kelp_plant", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.KELP))); public static final Block DRIED_KELP_BLOCK = register(new Block("dried_kelp_block", builder().destroyTime(0.5f))); public static final Block TURTLE_EGG = register(new Block("turtle_egg", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) - .intState(EGGS, 1, 4) - .intState(HATCH, 0, 2))); + .intState(EGGS) + .intState(HATCH))); public static final Block SNIFFER_EGG = register(new Block("sniffer_egg", builder().destroyTime(0.5f) - .intState(HATCH, 0, 2))); + .intState(HATCH))); public static final Block DEAD_TUBE_CORAL_BLOCK = register(new Block("dead_tube_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); public static final Block DEAD_BRAIN_CORAL_BLOCK = register(new Block("dead_brain_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); public static final Block DEAD_BUBBLE_CORAL_BLOCK = register(new Block("dead_bubble_coral_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); @@ -1784,16 +1784,16 @@ public final class Blocks { .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); public static final Block SEA_PICKLE = register(new Block("sea_pickle", builder().pushReaction(PistonBehavior.DESTROY) - .intState(PICKLES, 1, 4) + .intState(PICKLES) .booleanState(WATERLOGGED))); public static final Block BLUE_ICE = register(new Block("blue_ice", builder().destroyTime(2.8f))); public static final Block CONDUIT = register(new Block("conduit", builder().setBlockEntity().destroyTime(3.0f) .booleanState(WATERLOGGED))); public static final Block BAMBOO_SAPLING = register(new Block("bamboo_sapling", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.BAMBOO))); public static final Block BAMBOO = register(new Block("bamboo", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) - .intState(AGE_1, 0, 1) - .enumState(BAMBOO_LEAVES, "none", "small", "large") - .intState(STAGE, 0, 1))); + .intState(AGE_1) + .enumState(BAMBOO_LEAVES) + .intState(STAGE))); public static final Block POTTED_BAMBOO = register(new FlowerPotBlock("potted_bamboo", BAMBOO, builder().pushReaction(PistonBehavior.DESTROY))); public static final Block VOID_AIR = register(new Block("void_air", builder())); public static final Block CAVE_AIR = register(new Block("cave_air", builder())); @@ -1801,207 +1801,207 @@ public final class Blocks { .booleanState(DRAG))); public static final Block POLISHED_GRANITE_STAIRS = register(new Block("polished_granite_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block SMOOTH_RED_SANDSTONE_STAIRS = register(new Block("smooth_red_sandstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block MOSSY_STONE_BRICK_STAIRS = register(new Block("mossy_stone_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block POLISHED_DIORITE_STAIRS = register(new Block("polished_diorite_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block MOSSY_COBBLESTONE_STAIRS = register(new Block("mossy_cobblestone_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block END_STONE_BRICK_STAIRS = register(new Block("end_stone_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block STONE_STAIRS = register(new Block("stone_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block SMOOTH_SANDSTONE_STAIRS = register(new Block("smooth_sandstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block SMOOTH_QUARTZ_STAIRS = register(new Block("smooth_quartz_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block GRANITE_STAIRS = register(new Block("granite_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block ANDESITE_STAIRS = register(new Block("andesite_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block RED_NETHER_BRICK_STAIRS = register(new Block("red_nether_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block POLISHED_ANDESITE_STAIRS = register(new Block("polished_andesite_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block DIORITE_STAIRS = register(new Block("diorite_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block POLISHED_GRANITE_SLAB = register(new Block("polished_granite_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block SMOOTH_RED_SANDSTONE_SLAB = register(new Block("smooth_red_sandstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block MOSSY_STONE_BRICK_SLAB = register(new Block("mossy_stone_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block POLISHED_DIORITE_SLAB = register(new Block("polished_diorite_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block MOSSY_COBBLESTONE_SLAB = register(new Block("mossy_cobblestone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block END_STONE_BRICK_SLAB = register(new Block("end_stone_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block SMOOTH_SANDSTONE_SLAB = register(new Block("smooth_sandstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block SMOOTH_QUARTZ_SLAB = register(new Block("smooth_quartz_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block GRANITE_SLAB = register(new Block("granite_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block ANDESITE_SLAB = register(new Block("andesite_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block RED_NETHER_BRICK_SLAB = register(new Block("red_nether_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block POLISHED_ANDESITE_SLAB = register(new Block("polished_andesite_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block DIORITE_SLAB = register(new Block("diorite_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block BRICK_WALL = register(new Block("brick_wall", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(EAST_WALL, "none", "low", "tall") - .enumState(NORTH_WALL, "none", "low", "tall") - .enumState(SOUTH_WALL, "none", "low", "tall") + .enumState(EAST_WALL) + .enumState(NORTH_WALL) + .enumState(SOUTH_WALL) .booleanState(UP) .booleanState(WATERLOGGED) - .enumState(WEST_WALL, "none", "low", "tall"))); + .enumState(WEST_WALL))); public static final Block PRISMARINE_WALL = register(new Block("prismarine_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(EAST_WALL, "none", "low", "tall") - .enumState(NORTH_WALL, "none", "low", "tall") - .enumState(SOUTH_WALL, "none", "low", "tall") + .enumState(EAST_WALL) + .enumState(NORTH_WALL) + .enumState(SOUTH_WALL) .booleanState(UP) .booleanState(WATERLOGGED) - .enumState(WEST_WALL, "none", "low", "tall"))); + .enumState(WEST_WALL))); public static final Block RED_SANDSTONE_WALL = register(new Block("red_sandstone_wall", builder().requiresCorrectToolForDrops().destroyTime(0.8f) - .enumState(EAST_WALL, "none", "low", "tall") - .enumState(NORTH_WALL, "none", "low", "tall") - .enumState(SOUTH_WALL, "none", "low", "tall") + .enumState(EAST_WALL) + .enumState(NORTH_WALL) + .enumState(SOUTH_WALL) .booleanState(UP) .booleanState(WATERLOGGED) - .enumState(WEST_WALL, "none", "low", "tall"))); + .enumState(WEST_WALL))); public static final Block MOSSY_STONE_BRICK_WALL = register(new Block("mossy_stone_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(EAST_WALL, "none", "low", "tall") - .enumState(NORTH_WALL, "none", "low", "tall") - .enumState(SOUTH_WALL, "none", "low", "tall") + .enumState(EAST_WALL) + .enumState(NORTH_WALL) + .enumState(SOUTH_WALL) .booleanState(UP) .booleanState(WATERLOGGED) - .enumState(WEST_WALL, "none", "low", "tall"))); + .enumState(WEST_WALL))); public static final Block GRANITE_WALL = register(new Block("granite_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(EAST_WALL, "none", "low", "tall") - .enumState(NORTH_WALL, "none", "low", "tall") - .enumState(SOUTH_WALL, "none", "low", "tall") + .enumState(EAST_WALL) + .enumState(NORTH_WALL) + .enumState(SOUTH_WALL) .booleanState(UP) .booleanState(WATERLOGGED) - .enumState(WEST_WALL, "none", "low", "tall"))); + .enumState(WEST_WALL))); public static final Block STONE_BRICK_WALL = register(new Block("stone_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(EAST_WALL, "none", "low", "tall") - .enumState(NORTH_WALL, "none", "low", "tall") - .enumState(SOUTH_WALL, "none", "low", "tall") + .enumState(EAST_WALL) + .enumState(NORTH_WALL) + .enumState(SOUTH_WALL) .booleanState(UP) .booleanState(WATERLOGGED) - .enumState(WEST_WALL, "none", "low", "tall"))); + .enumState(WEST_WALL))); public static final Block MUD_BRICK_WALL = register(new Block("mud_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(EAST_WALL, "none", "low", "tall") - .enumState(NORTH_WALL, "none", "low", "tall") - .enumState(SOUTH_WALL, "none", "low", "tall") + .enumState(EAST_WALL) + .enumState(NORTH_WALL) + .enumState(SOUTH_WALL) .booleanState(UP) .booleanState(WATERLOGGED) - .enumState(WEST_WALL, "none", "low", "tall"))); + .enumState(WEST_WALL))); public static final Block NETHER_BRICK_WALL = register(new Block("nether_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(EAST_WALL, "none", "low", "tall") - .enumState(NORTH_WALL, "none", "low", "tall") - .enumState(SOUTH_WALL, "none", "low", "tall") + .enumState(EAST_WALL) + .enumState(NORTH_WALL) + .enumState(SOUTH_WALL) .booleanState(UP) .booleanState(WATERLOGGED) - .enumState(WEST_WALL, "none", "low", "tall"))); + .enumState(WEST_WALL))); public static final Block ANDESITE_WALL = register(new Block("andesite_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(EAST_WALL, "none", "low", "tall") - .enumState(NORTH_WALL, "none", "low", "tall") - .enumState(SOUTH_WALL, "none", "low", "tall") + .enumState(EAST_WALL) + .enumState(NORTH_WALL) + .enumState(SOUTH_WALL) .booleanState(UP) .booleanState(WATERLOGGED) - .enumState(WEST_WALL, "none", "low", "tall"))); + .enumState(WEST_WALL))); public static final Block RED_NETHER_BRICK_WALL = register(new Block("red_nether_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(EAST_WALL, "none", "low", "tall") - .enumState(NORTH_WALL, "none", "low", "tall") - .enumState(SOUTH_WALL, "none", "low", "tall") + .enumState(EAST_WALL) + .enumState(NORTH_WALL) + .enumState(SOUTH_WALL) .booleanState(UP) .booleanState(WATERLOGGED) - .enumState(WEST_WALL, "none", "low", "tall"))); + .enumState(WEST_WALL))); public static final Block SANDSTONE_WALL = register(new Block("sandstone_wall", builder().requiresCorrectToolForDrops().destroyTime(0.8f) - .enumState(EAST_WALL, "none", "low", "tall") - .enumState(NORTH_WALL, "none", "low", "tall") - .enumState(SOUTH_WALL, "none", "low", "tall") + .enumState(EAST_WALL) + .enumState(NORTH_WALL) + .enumState(SOUTH_WALL) .booleanState(UP) .booleanState(WATERLOGGED) - .enumState(WEST_WALL, "none", "low", "tall"))); + .enumState(WEST_WALL))); public static final Block END_STONE_BRICK_WALL = register(new Block("end_stone_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(3.0f) - .enumState(EAST_WALL, "none", "low", "tall") - .enumState(NORTH_WALL, "none", "low", "tall") - .enumState(SOUTH_WALL, "none", "low", "tall") + .enumState(EAST_WALL) + .enumState(NORTH_WALL) + .enumState(SOUTH_WALL) .booleanState(UP) .booleanState(WATERLOGGED) - .enumState(WEST_WALL, "none", "low", "tall"))); + .enumState(WEST_WALL))); public static final Block DIORITE_WALL = register(new Block("diorite_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(EAST_WALL, "none", "low", "tall") - .enumState(NORTH_WALL, "none", "low", "tall") - .enumState(SOUTH_WALL, "none", "low", "tall") + .enumState(EAST_WALL) + .enumState(NORTH_WALL) + .enumState(SOUTH_WALL) .booleanState(UP) .booleanState(WATERLOGGED) - .enumState(WEST_WALL, "none", "low", "tall"))); + .enumState(WEST_WALL))); public static final Block SCAFFOLDING = register(new Block("scaffolding", builder().pushReaction(PistonBehavior.DESTROY) .booleanState(BOTTOM) - .intState(STABILITY_DISTANCE, 0, 7) + .intState(STABILITY_DISTANCE) .booleanState(WATERLOGGED))); public static final Block LOOM = register(new Block("loom", builder().destroyTime(2.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); @@ -2017,7 +2017,7 @@ public final class Blocks { public static final Block CARTOGRAPHY_TABLE = register(new Block("cartography_table", builder().destroyTime(2.5f))); public static final Block FLETCHING_TABLE = register(new Block("fletching_table", builder().destroyTime(2.5f))); public static final Block GRINDSTONE = register(new Block("grindstone", builder().requiresCorrectToolForDrops().destroyTime(2.0f).pushReaction(PistonBehavior.BLOCK) - .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); public static final Block LECTERN = register(new LecternBlock("lectern", builder().setBlockEntity().destroyTime(2.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) @@ -2027,7 +2027,7 @@ public final class Blocks { public static final Block STONECUTTER = register(new Block("stonecutter", builder().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); public static final Block BELL = register(new Block("bell", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(5.0f).pushReaction(PistonBehavior.DESTROY) - .enumState(BELL_ATTACHMENT, "floor", "ceiling", "single_wall", "double_wall") + .enumState(BELL_ATTACHMENT) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); public static final Block LANTERN = register(new Block("lantern", builder().requiresCorrectToolForDrops().destroyTime(3.5f).pushReaction(PistonBehavior.DESTROY) @@ -2047,7 +2047,7 @@ public final class Blocks { .booleanState(SIGNAL_FIRE) .booleanState(WATERLOGGED))); public static final Block SWEET_BERRY_BUSH = register(new Block("sweet_berry_bush", builder().pushReaction(PistonBehavior.DESTROY) - .intState(AGE_3, 0, 3))); + .intState(AGE_3))); public static final Block WARPED_STEM = register(new Block("warped_stem", builder().destroyTime(2.0f) .enumState(AXIS, Axis.VALUES))); public static final Block STRIPPED_WARPED_STEM = register(new Block("stripped_warped_stem", builder().destroyTime(2.0f) @@ -2073,19 +2073,19 @@ public final class Blocks { public static final Block CRIMSON_FUNGUS = register(new Block("crimson_fungus", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block SHROOMLIGHT = register(new Block("shroomlight", builder().destroyTime(1.0f))); public static final Block WEEPING_VINES = register(new Block("weeping_vines", builder().pushReaction(PistonBehavior.DESTROY) - .intState(AGE_25, 0, 25))); + .intState(AGE_25))); public static final Block WEEPING_VINES_PLANT = register(new Block("weeping_vines_plant", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.WEEPING_VINES))); public static final Block TWISTING_VINES = register(new Block("twisting_vines", builder().pushReaction(PistonBehavior.DESTROY) - .intState(AGE_25, 0, 25))); + .intState(AGE_25))); public static final Block TWISTING_VINES_PLANT = register(new Block("twisting_vines_plant", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.TWISTING_VINES))); public static final Block CRIMSON_ROOTS = register(new Block("crimson_roots", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block CRIMSON_PLANKS = register(new Block("crimson_planks", builder().destroyTime(2.0f))); public static final Block WARPED_PLANKS = register(new Block("warped_planks", builder().destroyTime(2.0f))); public static final Block CRIMSON_SLAB = register(new Block("crimson_slab", builder().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block WARPED_SLAB = register(new Block("warped_slab", builder().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block CRIMSON_PRESSURE_PLATE = register(new Block("crimson_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED))); @@ -2105,13 +2105,13 @@ public final class Blocks { .booleanState(WEST))); public static final Block CRIMSON_TRAPDOOR = register(new TrapDoorBlock("crimson_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") + .enumState(HALF) .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); public static final Block WARPED_TRAPDOOR = register(new TrapDoorBlock("warped_trapdoor", builder().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") + .enumState(HALF) .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); @@ -2127,39 +2127,39 @@ public final class Blocks { .booleanState(POWERED))); public static final Block CRIMSON_STAIRS = register(new Block("crimson_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block WARPED_STAIRS = register(new Block("warped_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block CRIMSON_BUTTON = register(new Block("crimson_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) - .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); public static final Block WARPED_BUTTON = register(new Block("warped_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) - .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); public static final Block CRIMSON_DOOR = register(new DoorBlock("crimson_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") - .enumState(DOOR_HINGE, "left", "right") + .enumState(DOUBLE_BLOCK_HALF) + .enumState(DOOR_HINGE) .booleanState(OPEN) .booleanState(POWERED))); public static final Block WARPED_DOOR = register(new DoorBlock("warped_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") - .enumState(DOOR_HINGE, "left", "right") + .enumState(DOUBLE_BLOCK_HALF) + .enumState(DOOR_HINGE) .booleanState(OPEN) .booleanState(POWERED))); public static final Block CRIMSON_SIGN = register(new Block("crimson_sign", builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15) + .intState(ROTATION_16) .booleanState(WATERLOGGED))); public static final Block WARPED_SIGN = register(new Block("warped_sign", builder().setBlockEntity().destroyTime(1.0f) - .intState(ROTATION_16, 0, 15) + .intState(ROTATION_16) .booleanState(WATERLOGGED))); public static final Block CRIMSON_WALL_SIGN = register(new Block("crimson_wall_sign", builder().setBlockEntity().destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) @@ -2168,26 +2168,26 @@ public final class Blocks { .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); public static final Block STRUCTURE_BLOCK = register(new Block("structure_block", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(-1.0f) - .enumState(STRUCTUREBLOCK_MODE, "save", "load", "corner", "data"))); + .enumState(STRUCTUREBLOCK_MODE))); public static final Block JIGSAW = register(new Block("jigsaw", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(-1.0f) .enumState(ORIENTATION, FrontAndTop.VALUES))); public static final Block COMPOSTER = register(new Block("composter", builder().destroyTime(0.6f) - .intState(LEVEL_COMPOSTER, 0, 8))); + .intState(LEVEL_COMPOSTER))); public static final Block TARGET = register(new Block("target", builder().destroyTime(0.5f) - .intState(POWER, 0, 15))); + .intState(POWER))); public static final Block BEE_NEST = register(new Block("bee_nest", builder().setBlockEntity().destroyTime(0.3f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .intState(LEVEL_HONEY, 0, 5))); + .intState(LEVEL_HONEY))); public static final Block BEEHIVE = register(new Block("beehive", builder().setBlockEntity().destroyTime(0.6f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .intState(LEVEL_HONEY, 0, 5))); + .intState(LEVEL_HONEY))); public static final Block HONEY_BLOCK = register(new HoneyBlock("honey_block", builder())); public static final Block HONEYCOMB_BLOCK = register(new Block("honeycomb_block", builder().destroyTime(0.6f))); public static final Block NETHERITE_BLOCK = register(new Block("netherite_block", builder().requiresCorrectToolForDrops().destroyTime(50.0f))); public static final Block ANCIENT_DEBRIS = register(new Block("ancient_debris", builder().requiresCorrectToolForDrops().destroyTime(30.0f))); public static final Block CRYING_OBSIDIAN = register(new Block("crying_obsidian", builder().requiresCorrectToolForDrops().destroyTime(50.0f))); public static final Block RESPAWN_ANCHOR = register(new Block("respawn_anchor", builder().requiresCorrectToolForDrops().destroyTime(50.0f) - .intState(RESPAWN_ANCHOR_CHARGES, 0, 4))); + .intState(RESPAWN_ANCHOR_CHARGES))); public static final Block POTTED_CRIMSON_FUNGUS = register(new FlowerPotBlock("potted_crimson_fungus", CRIMSON_FUNGUS, builder().pushReaction(PistonBehavior.DESTROY))); public static final Block POTTED_WARPED_FUNGUS = register(new FlowerPotBlock("potted_warped_fungus", WARPED_FUNGUS, builder().pushReaction(PistonBehavior.DESTROY))); public static final Block POTTED_CRIMSON_ROOTS = register(new FlowerPotBlock("potted_crimson_roots", CRIMSON_ROOTS, builder().pushReaction(PistonBehavior.DESTROY))); @@ -2196,129 +2196,129 @@ public final class Blocks { public static final Block BLACKSTONE = register(new Block("blackstone", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); public static final Block BLACKSTONE_STAIRS = register(new Block("blackstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block BLACKSTONE_WALL = register(new Block("blackstone_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(EAST_WALL, "none", "low", "tall") - .enumState(NORTH_WALL, "none", "low", "tall") - .enumState(SOUTH_WALL, "none", "low", "tall") + .enumState(EAST_WALL) + .enumState(NORTH_WALL) + .enumState(SOUTH_WALL) .booleanState(UP) .booleanState(WATERLOGGED) - .enumState(WEST_WALL, "none", "low", "tall"))); + .enumState(WEST_WALL))); public static final Block BLACKSTONE_SLAB = register(new Block("blackstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block POLISHED_BLACKSTONE = register(new Block("polished_blackstone", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); public static final Block POLISHED_BLACKSTONE_BRICKS = register(new Block("polished_blackstone_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); public static final Block CRACKED_POLISHED_BLACKSTONE_BRICKS = register(new Block("cracked_polished_blackstone_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); public static final Block CHISELED_POLISHED_BLACKSTONE = register(new Block("chiseled_polished_blackstone", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); public static final Block POLISHED_BLACKSTONE_BRICK_SLAB = register(new Block("polished_blackstone_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block POLISHED_BLACKSTONE_BRICK_STAIRS = register(new Block("polished_blackstone_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block POLISHED_BLACKSTONE_BRICK_WALL = register(new Block("polished_blackstone_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(EAST_WALL, "none", "low", "tall") - .enumState(NORTH_WALL, "none", "low", "tall") - .enumState(SOUTH_WALL, "none", "low", "tall") + .enumState(EAST_WALL) + .enumState(NORTH_WALL) + .enumState(SOUTH_WALL) .booleanState(UP) .booleanState(WATERLOGGED) - .enumState(WEST_WALL, "none", "low", "tall"))); + .enumState(WEST_WALL))); public static final Block GILDED_BLACKSTONE = register(new Block("gilded_blackstone", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); public static final Block POLISHED_BLACKSTONE_STAIRS = register(new Block("polished_blackstone_stairs", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block POLISHED_BLACKSTONE_SLAB = register(new Block("polished_blackstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block POLISHED_BLACKSTONE_PRESSURE_PLATE = register(new Block("polished_blackstone_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED))); public static final Block POLISHED_BLACKSTONE_BUTTON = register(new Block("polished_blackstone_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) - .enumState(ATTACH_FACE, "floor", "wall", "ceiling") + .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); public static final Block POLISHED_BLACKSTONE_WALL = register(new Block("polished_blackstone_wall", builder().requiresCorrectToolForDrops().destroyTime(2.0f) - .enumState(EAST_WALL, "none", "low", "tall") - .enumState(NORTH_WALL, "none", "low", "tall") - .enumState(SOUTH_WALL, "none", "low", "tall") + .enumState(EAST_WALL) + .enumState(NORTH_WALL) + .enumState(SOUTH_WALL) .booleanState(UP) .booleanState(WATERLOGGED) - .enumState(WEST_WALL, "none", "low", "tall"))); + .enumState(WEST_WALL))); public static final Block CHISELED_NETHER_BRICKS = register(new Block("chiseled_nether_bricks", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); public static final Block CRACKED_NETHER_BRICKS = register(new Block("cracked_nether_bricks", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); public static final Block QUARTZ_BRICKS = register(new Block("quartz_bricks", builder().requiresCorrectToolForDrops().destroyTime(0.8f))); public static final Block CANDLE = register(new Block("candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) - .intState(CANDLES, 1, 4) + .intState(CANDLES) .booleanState(LIT) .booleanState(WATERLOGGED))); public static final Block WHITE_CANDLE = register(new Block("white_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) - .intState(CANDLES, 1, 4) + .intState(CANDLES) .booleanState(LIT) .booleanState(WATERLOGGED))); public static final Block ORANGE_CANDLE = register(new Block("orange_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) - .intState(CANDLES, 1, 4) + .intState(CANDLES) .booleanState(LIT) .booleanState(WATERLOGGED))); public static final Block MAGENTA_CANDLE = register(new Block("magenta_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) - .intState(CANDLES, 1, 4) + .intState(CANDLES) .booleanState(LIT) .booleanState(WATERLOGGED))); public static final Block LIGHT_BLUE_CANDLE = register(new Block("light_blue_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) - .intState(CANDLES, 1, 4) + .intState(CANDLES) .booleanState(LIT) .booleanState(WATERLOGGED))); public static final Block YELLOW_CANDLE = register(new Block("yellow_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) - .intState(CANDLES, 1, 4) + .intState(CANDLES) .booleanState(LIT) .booleanState(WATERLOGGED))); public static final Block LIME_CANDLE = register(new Block("lime_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) - .intState(CANDLES, 1, 4) + .intState(CANDLES) .booleanState(LIT) .booleanState(WATERLOGGED))); public static final Block PINK_CANDLE = register(new Block("pink_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) - .intState(CANDLES, 1, 4) + .intState(CANDLES) .booleanState(LIT) .booleanState(WATERLOGGED))); public static final Block GRAY_CANDLE = register(new Block("gray_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) - .intState(CANDLES, 1, 4) + .intState(CANDLES) .booleanState(LIT) .booleanState(WATERLOGGED))); public static final Block LIGHT_GRAY_CANDLE = register(new Block("light_gray_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) - .intState(CANDLES, 1, 4) + .intState(CANDLES) .booleanState(LIT) .booleanState(WATERLOGGED))); public static final Block CYAN_CANDLE = register(new Block("cyan_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) - .intState(CANDLES, 1, 4) + .intState(CANDLES) .booleanState(LIT) .booleanState(WATERLOGGED))); public static final Block PURPLE_CANDLE = register(new Block("purple_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) - .intState(CANDLES, 1, 4) + .intState(CANDLES) .booleanState(LIT) .booleanState(WATERLOGGED))); public static final Block BLUE_CANDLE = register(new Block("blue_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) - .intState(CANDLES, 1, 4) + .intState(CANDLES) .booleanState(LIT) .booleanState(WATERLOGGED))); public static final Block BROWN_CANDLE = register(new Block("brown_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) - .intState(CANDLES, 1, 4) + .intState(CANDLES) .booleanState(LIT) .booleanState(WATERLOGGED))); public static final Block GREEN_CANDLE = register(new Block("green_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) - .intState(CANDLES, 1, 4) + .intState(CANDLES) .booleanState(LIT) .booleanState(WATERLOGGED))); public static final Block RED_CANDLE = register(new Block("red_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) - .intState(CANDLES, 1, 4) + .intState(CANDLES) .booleanState(LIT) .booleanState(WATERLOGGED))); public static final Block BLACK_CANDLE = register(new Block("black_candle", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) - .intState(CANDLES, 1, 4) + .intState(CANDLES) .booleanState(LIT) .booleanState(WATERLOGGED))); public static final Block CANDLE_CAKE = register(new Block("candle_cake", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.CAKE) @@ -2371,65 +2371,65 @@ public final class Blocks { .booleanState(WATERLOGGED))); public static final Block TUFF = register(new Block("tuff", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); public static final Block TUFF_SLAB = register(new Block("tuff_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block TUFF_STAIRS = register(new Block("tuff_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block TUFF_WALL = register(new Block("tuff_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(EAST_WALL, "none", "low", "tall") - .enumState(NORTH_WALL, "none", "low", "tall") - .enumState(SOUTH_WALL, "none", "low", "tall") + .enumState(EAST_WALL) + .enumState(NORTH_WALL) + .enumState(SOUTH_WALL) .booleanState(UP) .booleanState(WATERLOGGED) - .enumState(WEST_WALL, "none", "low", "tall"))); + .enumState(WEST_WALL))); public static final Block POLISHED_TUFF = register(new Block("polished_tuff", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); public static final Block POLISHED_TUFF_SLAB = register(new Block("polished_tuff_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block POLISHED_TUFF_STAIRS = register(new Block("polished_tuff_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block POLISHED_TUFF_WALL = register(new Block("polished_tuff_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(EAST_WALL, "none", "low", "tall") - .enumState(NORTH_WALL, "none", "low", "tall") - .enumState(SOUTH_WALL, "none", "low", "tall") + .enumState(EAST_WALL) + .enumState(NORTH_WALL) + .enumState(SOUTH_WALL) .booleanState(UP) .booleanState(WATERLOGGED) - .enumState(WEST_WALL, "none", "low", "tall"))); + .enumState(WEST_WALL))); public static final Block CHISELED_TUFF = register(new Block("chiseled_tuff", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); public static final Block TUFF_BRICKS = register(new Block("tuff_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); public static final Block TUFF_BRICK_SLAB = register(new Block("tuff_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block TUFF_BRICK_STAIRS = register(new Block("tuff_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block TUFF_BRICK_WALL = register(new Block("tuff_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f) - .enumState(EAST_WALL, "none", "low", "tall") - .enumState(NORTH_WALL, "none", "low", "tall") - .enumState(SOUTH_WALL, "none", "low", "tall") + .enumState(EAST_WALL) + .enumState(NORTH_WALL) + .enumState(SOUTH_WALL) .booleanState(UP) .booleanState(WATERLOGGED) - .enumState(WEST_WALL, "none", "low", "tall"))); + .enumState(WEST_WALL))); public static final Block CHISELED_TUFF_BRICKS = register(new Block("chiseled_tuff_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); public static final Block CALCITE = register(new Block("calcite", builder().requiresCorrectToolForDrops().destroyTime(0.75f))); public static final Block TINTED_GLASS = register(new Block("tinted_glass", builder().destroyTime(0.3f))); public static final Block POWDER_SNOW = register(new Block("powder_snow", builder().destroyTime(0.25f))); public static final Block SCULK_SENSOR = register(new Block("sculk_sensor", builder().setBlockEntity().destroyTime(1.5f) - .intState(POWER, 0, 15) - .enumState(SCULK_SENSOR_PHASE, "inactive", "active", "cooldown") + .intState(POWER) + .enumState(SCULK_SENSOR_PHASE) .booleanState(WATERLOGGED))); public static final Block CALIBRATED_SCULK_SENSOR = register(new Block("calibrated_sculk_sensor", builder().setBlockEntity().destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .intState(POWER, 0, 15) - .enumState(SCULK_SENSOR_PHASE, "inactive", "active", "cooldown") + .intState(POWER) + .enumState(SCULK_SENSOR_PHASE) .booleanState(WATERLOGGED))); public static final Block SCULK = register(new Block("sculk", builder().destroyTime(0.2f))); public static final Block SCULK_VEIN = register(new Block("sculk_vein", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) @@ -2466,35 +2466,35 @@ public final class Blocks { public static final Block WAXED_CHISELED_COPPER = register(new Block("waxed_chiseled_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); public static final Block OXIDIZED_CUT_COPPER_STAIRS = register(new Block("oxidized_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block WEATHERED_CUT_COPPER_STAIRS = register(new Block("weathered_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block EXPOSED_CUT_COPPER_STAIRS = register(new Block("exposed_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block CUT_COPPER_STAIRS = register(new Block("cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block OXIDIZED_CUT_COPPER_SLAB = register(new Block("oxidized_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block WEATHERED_CUT_COPPER_SLAB = register(new Block("weathered_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block EXPOSED_CUT_COPPER_SLAB = register(new Block("exposed_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block CUT_COPPER_SLAB = register(new Block("cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block WAXED_COPPER_BLOCK = register(new Block("waxed_copper_block", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); public static final Block WAXED_WEATHERED_COPPER = register(new Block("waxed_weathered_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); @@ -2506,129 +2506,129 @@ public final class Blocks { public static final Block WAXED_CUT_COPPER = register(new Block("waxed_cut_copper", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); public static final Block WAXED_OXIDIZED_CUT_COPPER_STAIRS = register(new Block("waxed_oxidized_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block WAXED_WEATHERED_CUT_COPPER_STAIRS = register(new Block("waxed_weathered_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block WAXED_EXPOSED_CUT_COPPER_STAIRS = register(new Block("waxed_exposed_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block WAXED_CUT_COPPER_STAIRS = register(new Block("waxed_cut_copper_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block WAXED_OXIDIZED_CUT_COPPER_SLAB = register(new Block("waxed_oxidized_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block WAXED_WEATHERED_CUT_COPPER_SLAB = register(new Block("waxed_weathered_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block WAXED_EXPOSED_CUT_COPPER_SLAB = register(new Block("waxed_exposed_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block WAXED_CUT_COPPER_SLAB = register(new Block("waxed_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block COPPER_DOOR = register(new DoorBlock("copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") - .enumState(DOOR_HINGE, "left", "right") + .enumState(DOUBLE_BLOCK_HALF) + .enumState(DOOR_HINGE) .booleanState(OPEN) .booleanState(POWERED))); public static final Block EXPOSED_COPPER_DOOR = register(new DoorBlock("exposed_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") - .enumState(DOOR_HINGE, "left", "right") + .enumState(DOUBLE_BLOCK_HALF) + .enumState(DOOR_HINGE) .booleanState(OPEN) .booleanState(POWERED))); public static final Block OXIDIZED_COPPER_DOOR = register(new DoorBlock("oxidized_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") - .enumState(DOOR_HINGE, "left", "right") + .enumState(DOUBLE_BLOCK_HALF) + .enumState(DOOR_HINGE) .booleanState(OPEN) .booleanState(POWERED))); public static final Block WEATHERED_COPPER_DOOR = register(new DoorBlock("weathered_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") - .enumState(DOOR_HINGE, "left", "right") + .enumState(DOUBLE_BLOCK_HALF) + .enumState(DOOR_HINGE) .booleanState(OPEN) .booleanState(POWERED))); public static final Block WAXED_COPPER_DOOR = register(new DoorBlock("waxed_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") - .enumState(DOOR_HINGE, "left", "right") + .enumState(DOUBLE_BLOCK_HALF) + .enumState(DOOR_HINGE) .booleanState(OPEN) .booleanState(POWERED))); public static final Block WAXED_EXPOSED_COPPER_DOOR = register(new DoorBlock("waxed_exposed_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") - .enumState(DOOR_HINGE, "left", "right") + .enumState(DOUBLE_BLOCK_HALF) + .enumState(DOOR_HINGE) .booleanState(OPEN) .booleanState(POWERED))); public static final Block WAXED_OXIDIZED_COPPER_DOOR = register(new DoorBlock("waxed_oxidized_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") - .enumState(DOOR_HINGE, "left", "right") + .enumState(DOUBLE_BLOCK_HALF) + .enumState(DOOR_HINGE) .booleanState(OPEN) .booleanState(POWERED))); public static final Block WAXED_WEATHERED_COPPER_DOOR = register(new DoorBlock("waxed_weathered_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") - .enumState(DOOR_HINGE, "left", "right") + .enumState(DOUBLE_BLOCK_HALF) + .enumState(DOOR_HINGE) .booleanState(OPEN) .booleanState(POWERED))); public static final Block COPPER_TRAPDOOR = register(new TrapDoorBlock("copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") + .enumState(HALF) .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); public static final Block EXPOSED_COPPER_TRAPDOOR = register(new TrapDoorBlock("exposed_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") + .enumState(HALF) .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); public static final Block OXIDIZED_COPPER_TRAPDOOR = register(new TrapDoorBlock("oxidized_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") + .enumState(HALF) .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); public static final Block WEATHERED_COPPER_TRAPDOOR = register(new TrapDoorBlock("weathered_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") + .enumState(HALF) .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); public static final Block WAXED_COPPER_TRAPDOOR = register(new TrapDoorBlock("waxed_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") + .enumState(HALF) .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); public static final Block WAXED_EXPOSED_COPPER_TRAPDOOR = register(new TrapDoorBlock("waxed_exposed_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") + .enumState(HALF) .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); public static final Block WAXED_OXIDIZED_COPPER_TRAPDOOR = register(new TrapDoorBlock("waxed_oxidized_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") + .enumState(HALF) .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); public static final Block WAXED_WEATHERED_COPPER_TRAPDOOR = register(new TrapDoorBlock("waxed_weathered_copper_trapdoor", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") + .enumState(HALF) .booleanState(OPEN) .booleanState(POWERED) .booleanState(WATERLOGGED))); @@ -2677,12 +2677,12 @@ public final class Blocks { .booleanState(POWERED) .booleanState(WATERLOGGED))); public static final Block POINTED_DRIPSTONE = register(new Block("pointed_dripstone", builder().destroyTime(1.5f).pushReaction(PistonBehavior.DESTROY) - .enumState(DRIPSTONE_THICKNESS, "tip_merge", "tip", "frustum", "middle", "base") + .enumState(DRIPSTONE_THICKNESS) .enumState(VERTICAL_DIRECTION, Direction.UP, Direction.DOWN) .booleanState(WATERLOGGED))); public static final Block DRIPSTONE_BLOCK = register(new Block("dripstone_block", builder().requiresCorrectToolForDrops().destroyTime(1.5f))); public static final Block CAVE_VINES = register(new Block("cave_vines", builder().pushReaction(PistonBehavior.DESTROY) - .intState(AGE_25, 0, 25) + .intState(AGE_25) .booleanState(BERRIES))); public static final Block CAVE_VINES_PLANT = register(new Block("cave_vines_plant", builder().pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.GLOW_BERRIES) .booleanState(BERRIES))); @@ -2692,18 +2692,18 @@ public final class Blocks { public static final Block MOSS_CARPET = register(new Block("moss_carpet", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY))); public static final Block PINK_PETALS = register(new Block("pink_petals", builder().pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .intState(FLOWER_AMOUNT, 1, 4))); + .intState(FLOWER_AMOUNT))); public static final Block MOSS_BLOCK = register(new Block("moss_block", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY))); public static final Block BIG_DRIPLEAF = register(new Block("big_dripleaf", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(TILT, "none", "unstable", "partial", "full") + .enumState(TILT) .booleanState(WATERLOGGED))); public static final Block BIG_DRIPLEAF_STEM = register(new Block("big_dripleaf_stem", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); public static final Block SMALL_DRIPLEAF = register(new Block("small_dripleaf", builder().pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(DOUBLE_BLOCK_HALF, "upper", "lower") + .enumState(DOUBLE_BLOCK_HALF) .booleanState(WATERLOGGED))); public static final Block HANGING_ROOTS = register(new Block("hanging_roots", builder().pushReaction(PistonBehavior.DESTROY) .booleanState(WATERLOGGED))); @@ -2714,67 +2714,67 @@ public final class Blocks { public static final Block COBBLED_DEEPSLATE = register(new Block("cobbled_deepslate", builder().requiresCorrectToolForDrops().destroyTime(3.5f))); public static final Block COBBLED_DEEPSLATE_STAIRS = register(new Block("cobbled_deepslate_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block COBBLED_DEEPSLATE_SLAB = register(new Block("cobbled_deepslate_slab", builder().requiresCorrectToolForDrops().destroyTime(3.5f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block COBBLED_DEEPSLATE_WALL = register(new Block("cobbled_deepslate_wall", builder().requiresCorrectToolForDrops().destroyTime(3.5f) - .enumState(EAST_WALL, "none", "low", "tall") - .enumState(NORTH_WALL, "none", "low", "tall") - .enumState(SOUTH_WALL, "none", "low", "tall") + .enumState(EAST_WALL) + .enumState(NORTH_WALL) + .enumState(SOUTH_WALL) .booleanState(UP) .booleanState(WATERLOGGED) - .enumState(WEST_WALL, "none", "low", "tall"))); + .enumState(WEST_WALL))); public static final Block POLISHED_DEEPSLATE = register(new Block("polished_deepslate", builder().requiresCorrectToolForDrops().destroyTime(3.5f))); public static final Block POLISHED_DEEPSLATE_STAIRS = register(new Block("polished_deepslate_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block POLISHED_DEEPSLATE_SLAB = register(new Block("polished_deepslate_slab", builder().requiresCorrectToolForDrops().destroyTime(3.5f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block POLISHED_DEEPSLATE_WALL = register(new Block("polished_deepslate_wall", builder().requiresCorrectToolForDrops().destroyTime(3.5f) - .enumState(EAST_WALL, "none", "low", "tall") - .enumState(NORTH_WALL, "none", "low", "tall") - .enumState(SOUTH_WALL, "none", "low", "tall") + .enumState(EAST_WALL) + .enumState(NORTH_WALL) + .enumState(SOUTH_WALL) .booleanState(UP) .booleanState(WATERLOGGED) - .enumState(WEST_WALL, "none", "low", "tall"))); + .enumState(WEST_WALL))); public static final Block DEEPSLATE_TILES = register(new Block("deepslate_tiles", builder().requiresCorrectToolForDrops().destroyTime(3.5f))); public static final Block DEEPSLATE_TILE_STAIRS = register(new Block("deepslate_tile_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block DEEPSLATE_TILE_SLAB = register(new Block("deepslate_tile_slab", builder().requiresCorrectToolForDrops().destroyTime(3.5f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block DEEPSLATE_TILE_WALL = register(new Block("deepslate_tile_wall", builder().requiresCorrectToolForDrops().destroyTime(3.5f) - .enumState(EAST_WALL, "none", "low", "tall") - .enumState(NORTH_WALL, "none", "low", "tall") - .enumState(SOUTH_WALL, "none", "low", "tall") + .enumState(EAST_WALL) + .enumState(NORTH_WALL) + .enumState(SOUTH_WALL) .booleanState(UP) .booleanState(WATERLOGGED) - .enumState(WEST_WALL, "none", "low", "tall"))); + .enumState(WEST_WALL))); public static final Block DEEPSLATE_BRICKS = register(new Block("deepslate_bricks", builder().requiresCorrectToolForDrops().destroyTime(3.5f))); public static final Block DEEPSLATE_BRICK_STAIRS = register(new Block("deepslate_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) - .enumState(HALF, "top", "bottom") - .enumState(STAIRS_SHAPE, "straight", "inner_left", "inner_right", "outer_left", "outer_right") + .enumState(HALF) + .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); public static final Block DEEPSLATE_BRICK_SLAB = register(new Block("deepslate_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(3.5f) - .enumState(SLAB_TYPE, "top", "bottom", "double") + .enumState(SLAB_TYPE) .booleanState(WATERLOGGED))); public static final Block DEEPSLATE_BRICK_WALL = register(new Block("deepslate_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(3.5f) - .enumState(EAST_WALL, "none", "low", "tall") - .enumState(NORTH_WALL, "none", "low", "tall") - .enumState(SOUTH_WALL, "none", "low", "tall") + .enumState(EAST_WALL) + .enumState(NORTH_WALL) + .enumState(SOUTH_WALL) .booleanState(UP) .booleanState(WATERLOGGED) - .enumState(WEST_WALL, "none", "low", "tall"))); + .enumState(WEST_WALL))); public static final Block CHISELED_DEEPSLATE = register(new Block("chiseled_deepslate", builder().requiresCorrectToolForDrops().destroyTime(3.5f))); public static final Block CRACKED_DEEPSLATE_BRICKS = register(new Block("cracked_deepslate_bricks", builder().requiresCorrectToolForDrops().destroyTime(3.5f))); public static final Block CRACKED_DEEPSLATE_TILES = register(new Block("cracked_deepslate_tiles", builder().requiresCorrectToolForDrops().destroyTime(3.5f))); @@ -2804,11 +2804,11 @@ public final class Blocks { .booleanState(TRIGGERED))); public static final Block TRIAL_SPAWNER = register(new Block("trial_spawner", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(50.0f) .booleanState(OMINOUS) - .enumState(TRIAL_SPAWNER_STATE, "inactive", "waiting_for_players", "active", "waiting_for_reward_ejection", "ejecting_reward", "cooldown"))); + .enumState(TRIAL_SPAWNER_STATE))); public static final Block VAULT = register(new Block("vault", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(50.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OMINOUS) - .enumState(VAULT_STATE, "inactive", "active", "unlocking", "ejecting"))); + .enumState(VAULT_STATE))); public static final Block HEAVY_CORE = register(new Block("heavy_core", builder().destroyTime(10.0f) .booleanState(WATERLOGGED))); diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/BasicEnumProperty.java b/core/src/main/java/org/geysermc/geyser/level/block/property/BasicEnumProperty.java new file mode 100644 index 000000000..f55b85d7b --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/property/BasicEnumProperty.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 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.level.block.property; + +import java.util.List; + +/** + * Represents enums we don't need classes for in Geyser. + */ +public final class BasicEnumProperty extends Property { + private final List values; + + private BasicEnumProperty(String name, List values) { + super(name); + this.values = values; + } + + @Override + public int valuesCount() { + return this.values.size(); + } + + @Override + public int indexOf(String value) { + int index = this.values.indexOf(value); + if (index == -1) { + throw new IllegalStateException("Property " + this + " does not have value " + value); + } + return index; + } + + @SuppressWarnings("unchecked") + public T values() { + return (T) this.values; + } + + public static BasicEnumProperty create(String name, String... values) { + return new BasicEnumProperty(name, List.of(values)); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/BooleanProperty.java b/core/src/main/java/org/geysermc/geyser/level/block/property/BooleanProperty.java new file mode 100644 index 000000000..56877f537 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/property/BooleanProperty.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 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.level.block.property; + +public final class BooleanProperty extends Property { + private BooleanProperty(String name) { + super(name); + } + + @Override + public int valuesCount() { + return 2; + } + + @Override + public int indexOf(Boolean value) { + return value ? 0 : 1; + } + + public static BooleanProperty create(String name) { + return new BooleanProperty(name); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/EnumProperty.java b/core/src/main/java/org/geysermc/geyser/level/block/property/EnumProperty.java new file mode 100644 index 000000000..e31f665f9 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/property/EnumProperty.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 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.level.block.property; + +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; + +public final class EnumProperty> extends Property { + private final IntList ordinalValues; + + /** + * @param values all possible values of this enum. + */ + private EnumProperty(String name, T[] values) { + super(name); + this.ordinalValues = new IntArrayList(values.length); + for (T anEnum : values) { + this.ordinalValues.add(anEnum.ordinal()); + } + } + + @Override + public int valuesCount() { + return this.ordinalValues.size(); + } + + @Override + public int indexOf(T value) { + return this.ordinalValues.indexOf(value.ordinal()); + } + + @SafeVarargs + public static > EnumProperty create(String name, T... values) { + return new EnumProperty<>(name, values); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/IntegerProperty.java b/core/src/main/java/org/geysermc/geyser/level/block/property/IntegerProperty.java new file mode 100644 index 000000000..a772f414d --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/property/IntegerProperty.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 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.level.block.property; + +public final class IntegerProperty extends Property { + private final int offset; + private final int valuesCount; + + private IntegerProperty(String name, int low, int high) { + super(name); + this.offset = low; + this.valuesCount = high - low; + } + + @Override + public int valuesCount() { + return this.valuesCount; + } + + @Override + public int indexOf(Integer value) { + return value - this.offset; + } + + public int low() { + return this.offset; + } + + public int high() { + return this.offset + this.valuesCount; + } + + public static IntegerProperty create(String name, int low, int high) { + return new IntegerProperty(name, low, high); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java b/core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java index 7df09003d..7efa2ef80 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/property/Properties.java @@ -29,118 +29,118 @@ import org.geysermc.geyser.level.physics.Axis; import org.geysermc.geyser.level.physics.Direction; public final class Properties { - public static final Property ATTACHED = Property.create("attached"); - public static final Property BOTTOM = Property.create("bottom"); - public static final Property CONDITIONAL = Property.create("conditional"); - public static final Property DISARMED = Property.create("disarmed"); - public static final Property DRAG = Property.create("drag"); - public static final Property ENABLED = Property.create("enabled"); - public static final Property EXTENDED = Property.create("extended"); - public static final Property EYE = Property.create("eye"); - public static final Property FALLING = Property.create("falling"); - public static final Property HANGING = Property.create("hanging"); - public static final Property HAS_BOTTLE_0 = Property.create("has_bottle_0"); - public static final Property HAS_BOTTLE_1 = Property.create("has_bottle_1"); - public static final Property HAS_BOTTLE_2 = Property.create("has_bottle_2"); - public static final Property HAS_RECORD = Property.create("has_record"); - public static final Property HAS_BOOK = Property.create("has_book"); - public static final Property INVERTED = Property.create("inverted"); - public static final Property IN_WALL = Property.create("in_wall"); - public static final Property LIT = Property.create("lit"); - public static final Property LOCKED = Property.create("locked"); - public static final Property OCCUPIED = Property.create("occupied"); - public static final Property OPEN = Property.create("open"); - public static final Property PERSISTENT = Property.create("persistent"); - public static final Property POWERED = Property.create("powered"); - public static final Property SHORT = Property.create("short"); - public static final Property SIGNAL_FIRE = Property.create("signal_fire"); - public static final Property SNOWY = Property.create("snowy"); - public static final Property TRIGGERED = Property.create("triggered"); - public static final Property UNSTABLE = Property.create("unstable"); - public static final Property WATERLOGGED = Property.create("waterlogged"); - public static final Property BERRIES = Property.create("berries"); - public static final Property BLOOM = Property.create("bloom"); - public static final Property SHRIEKING = Property.create("shrieking"); - public static final Property CAN_SUMMON = Property.create("can_summon"); - public static final Property HORIZONTAL_AXIS = Property.create("axis"); - public static final Property AXIS = Property.create("axis"); - public static final Property UP = Property.create("up"); - public static final Property DOWN = Property.create("down"); - public static final Property NORTH = Property.create("north"); - public static final Property EAST = Property.create("east"); - public static final Property SOUTH = Property.create("south"); - public static final Property WEST = Property.create("west"); - public static final Property FACING = Property.create("facing"); - public static final Property FACING_HOPPER = Property.create("facing"); - public static final Property HORIZONTAL_FACING = Property.create("facing"); - public static final Property FLOWER_AMOUNT = Property.create("flower_amount"); - public static final Property ORIENTATION = Property.create("orientation"); - public static final Property ATTACH_FACE = Property.create("face"); - public static final Property BELL_ATTACHMENT = Property.create("attachment"); - public static final Property EAST_WALL = Property.create("east"); - public static final Property NORTH_WALL = Property.create("north"); - public static final Property SOUTH_WALL = Property.create("south"); - public static final Property WEST_WALL = Property.create("west"); - public static final Property EAST_REDSTONE = Property.create("east"); - public static final Property NORTH_REDSTONE = Property.create("north"); - public static final Property SOUTH_REDSTONE = Property.create("south"); - public static final Property WEST_REDSTONE = Property.create("west"); - public static final Property DOUBLE_BLOCK_HALF = Property.create("half"); - public static final Property HALF = Property.create("half"); - public static final Property RAIL_SHAPE = Property.create("shape"); - public static final Property RAIL_SHAPE_STRAIGHT = Property.create("shape"); - public static final Property AGE_1 = Property.create("age"); - public static final Property AGE_2 = Property.create("age"); - public static final Property AGE_3 = Property.create("age"); - public static final Property AGE_4 = Property.create("age"); - public static final Property AGE_5 = Property.create("age"); - public static final Property AGE_7 = Property.create("age"); - public static final Property AGE_15 = Property.create("age"); - public static final Property AGE_25 = Property.create("age"); - public static final Property BITES = Property.create("bites"); - public static final Property CANDLES = Property.create("candles"); - public static final Property DELAY = Property.create("delay"); - public static final Property DISTANCE = Property.create("distance"); - public static final Property EGGS = Property.create("eggs"); - public static final Property HATCH = Property.create("hatch"); - public static final Property LAYERS = Property.create("layers"); - public static final Property LEVEL_CAULDRON = Property.create("level"); - public static final Property LEVEL_COMPOSTER = Property.create("level"); - public static final Property LEVEL_FLOWING = Property.create("level"); - public static final Property LEVEL_HONEY = Property.create("honey_level"); - public static final Property LEVEL = Property.create("level"); - public static final Property MOISTURE = Property.create("moisture"); - public static final Property NOTE = Property.create("note"); - public static final Property PICKLES = Property.create("pickles"); - public static final Property POWER = Property.create("power"); - public static final Property STAGE = Property.create("stage"); - public static final Property STABILITY_DISTANCE = Property.create("distance"); - public static final Property RESPAWN_ANCHOR_CHARGES = Property.create("charges"); - public static final Property ROTATION_16 = Property.create("rotation"); - public static final Property BED_PART = Property.create("part"); - public static final Property CHEST_TYPE = Property.create("type"); - public static final Property MODE_COMPARATOR = Property.create("mode"); - public static final Property DOOR_HINGE = Property.create("hinge"); - public static final Property NOTEBLOCK_INSTRUMENT = Property.create("instrument"); - public static final Property PISTON_TYPE = Property.create("type"); - public static final Property SLAB_TYPE = Property.create("type"); - public static final Property STAIRS_SHAPE = Property.create("shape"); - public static final Property STRUCTUREBLOCK_MODE = Property.create("mode"); - public static final Property BAMBOO_LEAVES = Property.create("leaves"); - public static final Property TILT = Property.create("tilt"); - public static final Property VERTICAL_DIRECTION = Property.create("vertical_direction"); - public static final Property DRIPSTONE_THICKNESS = Property.create("thickness"); - public static final Property SCULK_SENSOR_PHASE = Property.create("sculk_sensor_phase"); - public static final Property CHISELED_BOOKSHELF_SLOT_0_OCCUPIED = Property.create("slot_0_occupied"); - public static final Property CHISELED_BOOKSHELF_SLOT_1_OCCUPIED = Property.create("slot_1_occupied"); - public static final Property CHISELED_BOOKSHELF_SLOT_2_OCCUPIED = Property.create("slot_2_occupied"); - public static final Property CHISELED_BOOKSHELF_SLOT_3_OCCUPIED = Property.create("slot_3_occupied"); - public static final Property CHISELED_BOOKSHELF_SLOT_4_OCCUPIED = Property.create("slot_4_occupied"); - public static final Property CHISELED_BOOKSHELF_SLOT_5_OCCUPIED = Property.create("slot_5_occupied"); - public static final Property DUSTED = Property.create("dusted"); - public static final Property CRACKED = Property.create("cracked"); - public static final Property CRAFTING = Property.create("crafting"); - public static final Property TRIAL_SPAWNER_STATE = Property.create("trial_spawner_state"); - public static final Property VAULT_STATE = Property.create("vault_state"); - public static final Property OMINOUS = Property.create("ominous"); + public static final BooleanProperty ATTACHED = BooleanProperty.create("attached"); + public static final BooleanProperty BOTTOM = BooleanProperty.create("bottom"); + public static final BooleanProperty CONDITIONAL = BooleanProperty.create("conditional"); + public static final BooleanProperty DISARMED = BooleanProperty.create("disarmed"); + public static final BooleanProperty DRAG = BooleanProperty.create("drag"); + public static final BooleanProperty ENABLED = BooleanProperty.create("enabled"); + public static final BooleanProperty EXTENDED = BooleanProperty.create("extended"); + public static final BooleanProperty EYE = BooleanProperty.create("eye"); + public static final BooleanProperty FALLING = BooleanProperty.create("falling"); + public static final BooleanProperty HANGING = BooleanProperty.create("hanging"); + public static final BooleanProperty HAS_BOTTLE_0 = BooleanProperty.create("has_bottle_0"); + public static final BooleanProperty HAS_BOTTLE_1 = BooleanProperty.create("has_bottle_1"); + public static final BooleanProperty HAS_BOTTLE_2 = BooleanProperty.create("has_bottle_2"); + public static final BooleanProperty HAS_RECORD = BooleanProperty.create("has_record"); + public static final BooleanProperty HAS_BOOK = BooleanProperty.create("has_book"); + public static final BooleanProperty INVERTED = BooleanProperty.create("inverted"); + public static final BooleanProperty IN_WALL = BooleanProperty.create("in_wall"); + public static final BooleanProperty LIT = BooleanProperty.create("lit"); + public static final BooleanProperty LOCKED = BooleanProperty.create("locked"); + public static final BooleanProperty OCCUPIED = BooleanProperty.create("occupied"); + public static final BooleanProperty OPEN = BooleanProperty.create("open"); + public static final BooleanProperty PERSISTENT = BooleanProperty.create("persistent"); + public static final BooleanProperty POWERED = BooleanProperty.create("powered"); + public static final BooleanProperty SHORT = BooleanProperty.create("short"); + public static final BooleanProperty SIGNAL_FIRE = BooleanProperty.create("signal_fire"); + public static final BooleanProperty SNOWY = BooleanProperty.create("snowy"); + public static final BooleanProperty TRIGGERED = BooleanProperty.create("triggered"); + public static final BooleanProperty UNSTABLE = BooleanProperty.create("unstable"); + public static final BooleanProperty WATERLOGGED = BooleanProperty.create("waterlogged"); + public static final BooleanProperty BERRIES = BooleanProperty.create("berries"); + public static final BooleanProperty BLOOM = BooleanProperty.create("bloom"); + public static final BooleanProperty SHRIEKING = BooleanProperty.create("shrieking"); + public static final BooleanProperty CAN_SUMMON = BooleanProperty.create("can_summon"); + public static final EnumProperty HORIZONTAL_AXIS = EnumProperty.create("axis", Axis.X, Axis.Z); + public static final EnumProperty AXIS = EnumProperty.create("axis", Axis.VALUES); + public static final BooleanProperty UP = BooleanProperty.create("up"); + public static final BooleanProperty DOWN = BooleanProperty.create("down"); + public static final BooleanProperty NORTH = BooleanProperty.create("north"); + public static final BooleanProperty EAST = BooleanProperty.create("east"); + public static final BooleanProperty SOUTH = BooleanProperty.create("south"); + public static final BooleanProperty WEST = BooleanProperty.create("west"); + public static final EnumProperty FACING = EnumProperty.create("facing", Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN); + public static final EnumProperty FACING_HOPPER = EnumProperty.create("facing", Direction.DOWN, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST); + public static final EnumProperty HORIZONTAL_FACING = EnumProperty.create("facing", Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST); + public static final IntegerProperty FLOWER_AMOUNT = IntegerProperty.create("flower_amount", 1, 4); + public static final EnumProperty ORIENTATION = EnumProperty.create("orientation", FrontAndTop.VALUES); + public static final BasicEnumProperty ATTACH_FACE = BasicEnumProperty.create("face", "floor", "wall", "ceiling"); + public static final BasicEnumProperty BELL_ATTACHMENT = BasicEnumProperty.create("attachment", "floor", "ceiling", "single_wall", "double_wall"); + public static final BasicEnumProperty EAST_WALL = BasicEnumProperty.create("east", "none", "low", "tall"); + public static final BasicEnumProperty NORTH_WALL = BasicEnumProperty.create("north", "none", "low", "tall"); + public static final BasicEnumProperty SOUTH_WALL = BasicEnumProperty.create("south", "none", "low", "tall"); + public static final BasicEnumProperty WEST_WALL = BasicEnumProperty.create("west", "none", "low", "tall"); + public static final BasicEnumProperty EAST_REDSTONE = BasicEnumProperty.create("east", "up", "side", "none"); + public static final BasicEnumProperty NORTH_REDSTONE = BasicEnumProperty.create("north", "up", "side", "none"); + public static final BasicEnumProperty SOUTH_REDSTONE = BasicEnumProperty.create("south", "up", "side", "none"); + public static final BasicEnumProperty WEST_REDSTONE = BasicEnumProperty.create("west", "up", "side", "none"); + public static final BasicEnumProperty DOUBLE_BLOCK_HALF = BasicEnumProperty.create("half", "upper", "lower"); + public static final BasicEnumProperty HALF = BasicEnumProperty.create("half", "top", "bottom"); + public static final BasicEnumProperty RAIL_SHAPE = BasicEnumProperty.create("shape", "north_south", "east_west", "ascending_east", "ascending_west", "ascending_north", "ascending_south", "south_east", "south_west", "north_west", "north_east"); + public static final BasicEnumProperty RAIL_SHAPE_STRAIGHT = BasicEnumProperty.create("shape", "north_south", "east_west", "ascending_east", "ascending_west", "ascending_north", "ascending_south"); + public static final IntegerProperty AGE_1 = IntegerProperty.create("age", 0, 1); + public static final IntegerProperty AGE_2 = IntegerProperty.create("age", 0, 2); + public static final IntegerProperty AGE_3 = IntegerProperty.create("age", 0, 3); + public static final IntegerProperty AGE_4 = IntegerProperty.create("age", 0, 4); + public static final IntegerProperty AGE_5 = IntegerProperty.create("age", 0, 5); + public static final IntegerProperty AGE_7 = IntegerProperty.create("age", 0, 7); + public static final IntegerProperty AGE_15 = IntegerProperty.create("age", 0, 15); + public static final IntegerProperty AGE_25 = IntegerProperty.create("age", 0, 25); + public static final IntegerProperty BITES = IntegerProperty.create("bites", 0, 6); + public static final IntegerProperty CANDLES = IntegerProperty.create("candles", 1, 4); + public static final IntegerProperty DELAY = IntegerProperty.create("delay", 1, 4); + public static final IntegerProperty DISTANCE = IntegerProperty.create("distance", 1, 7); + public static final IntegerProperty EGGS = IntegerProperty.create("eggs", 1, 4); + public static final IntegerProperty HATCH = IntegerProperty.create("hatch", 0, 2); + public static final IntegerProperty LAYERS = IntegerProperty.create("layers", 1, 8); + public static final IntegerProperty LEVEL_CAULDRON = IntegerProperty.create("level", 1, 3); + public static final IntegerProperty LEVEL_COMPOSTER = IntegerProperty.create("level", 0, 8); + public static final IntegerProperty LEVEL_FLOWING = IntegerProperty.create("level", 1, 8); + public static final IntegerProperty LEVEL_HONEY = IntegerProperty.create("honey_level", 0, 5); + public static final IntegerProperty LEVEL = IntegerProperty.create("level", 0, 15); + public static final IntegerProperty MOISTURE = IntegerProperty.create("moisture", 0, 7); + public static final IntegerProperty NOTE = IntegerProperty.create("note", 0, 24); + public static final IntegerProperty PICKLES = IntegerProperty.create("pickles", 1, 4); + public static final IntegerProperty POWER = IntegerProperty.create("power", 0, 15); + public static final IntegerProperty STAGE = IntegerProperty.create("stage", 0, 1); + public static final IntegerProperty STABILITY_DISTANCE = IntegerProperty.create("distance", 0, 7); + public static final IntegerProperty RESPAWN_ANCHOR_CHARGES = IntegerProperty.create("charges", 0, 4); + public static final IntegerProperty ROTATION_16 = IntegerProperty.create("rotation", 0, 15); + public static final BasicEnumProperty BED_PART = BasicEnumProperty.create("part", "head", "foot"); + public static final EnumProperty CHEST_TYPE = EnumProperty.create("type", ChestType.VALUES); + public static final BasicEnumProperty MODE_COMPARATOR = BasicEnumProperty.create("mode", "compare", "subtract"); + public static final BasicEnumProperty DOOR_HINGE = BasicEnumProperty.create("hinge", "left", "right"); + public static final BasicEnumProperty NOTEBLOCK_INSTRUMENT = BasicEnumProperty.create("instrument", "harp", "basedrum", "snare", "hat", "bass", "flute", "bell", "guitar", "chime", "xylophone", "iron_xylophone", "cow_bell", "didgeridoo", "bit", "banjo", "pling", "zombie", "skeleton", "creeper", "dragon", "wither_skeleton", "piglin", "custom_head"); + public static final BasicEnumProperty PISTON_TYPE = BasicEnumProperty.create("type", "normal", "sticky"); + public static final BasicEnumProperty SLAB_TYPE = BasicEnumProperty.create("type", "top", "bottom", "double"); + public static final BasicEnumProperty STAIRS_SHAPE = BasicEnumProperty.create("shape", "straight", "inner_left", "inner_right", "outer_left", "outer_right"); + public static final BasicEnumProperty STRUCTUREBLOCK_MODE = BasicEnumProperty.create("mode", "save", "load", "corner", "data"); + public static final BasicEnumProperty BAMBOO_LEAVES = BasicEnumProperty.create("leaves", "none", "small", "large"); + public static final BasicEnumProperty TILT = BasicEnumProperty.create("tilt", "none", "unstable", "partial", "full"); + public static final EnumProperty VERTICAL_DIRECTION = EnumProperty.create("vertical_direction", Direction.UP, Direction.DOWN); + public static final BasicEnumProperty DRIPSTONE_THICKNESS = BasicEnumProperty.create("thickness", "tip_merge", "tip", "frustum", "middle", "base"); + public static final BasicEnumProperty SCULK_SENSOR_PHASE = BasicEnumProperty.create("sculk_sensor_phase", "inactive", "active", "cooldown"); + public static final BooleanProperty CHISELED_BOOKSHELF_SLOT_0_OCCUPIED = BooleanProperty.create("slot_0_occupied"); + public static final BooleanProperty CHISELED_BOOKSHELF_SLOT_1_OCCUPIED = BooleanProperty.create("slot_1_occupied"); + public static final BooleanProperty CHISELED_BOOKSHELF_SLOT_2_OCCUPIED = BooleanProperty.create("slot_2_occupied"); + public static final BooleanProperty CHISELED_BOOKSHELF_SLOT_3_OCCUPIED = BooleanProperty.create("slot_3_occupied"); + public static final BooleanProperty CHISELED_BOOKSHELF_SLOT_4_OCCUPIED = BooleanProperty.create("slot_4_occupied"); + public static final BooleanProperty CHISELED_BOOKSHELF_SLOT_5_OCCUPIED = BooleanProperty.create("slot_5_occupied"); + public static final IntegerProperty DUSTED = IntegerProperty.create("dusted", 0, 3); + public static final BooleanProperty CRACKED = BooleanProperty.create("cracked"); + public static final BooleanProperty CRAFTING = BooleanProperty.create("crafting"); + public static final BasicEnumProperty TRIAL_SPAWNER_STATE = BasicEnumProperty.create("trial_spawner_state", "inactive", "waiting_for_players", "active", "waiting_for_reward_ejection", "ejecting_reward", "cooldown"); + public static final BasicEnumProperty VAULT_STATE = BasicEnumProperty.create("vault_state", "inactive", "active", "unlocking", "ejecting"); + public static final BooleanProperty OMINOUS = BooleanProperty.create("ominous"); } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/Property.java b/core/src/main/java/org/geysermc/geyser/level/block/property/Property.java index ca5f62daa..0c4713124 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/property/Property.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/property/Property.java @@ -25,10 +25,10 @@ package org.geysermc.geyser.level.block.property; -public class Property> { +public abstract class Property> { private final String name; - public Property(String name) { + protected Property(String name) { this.name = name; } @@ -36,12 +36,12 @@ public class Property> { return name; } + public abstract int valuesCount(); + + public abstract int indexOf(T value); + @Override public String toString() { return getClass().getSimpleName() + "[" + name + "]"; } - - public static > Property create(String name) { - return new Property<>(name); - } } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java b/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java index b31c9aeb5..9fe70c0f1 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java @@ -27,9 +27,6 @@ package org.geysermc.geyser.level.block.type; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; -import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap; -import it.unimi.dsi.fastutil.objects.Reference2ObjectMap; -import it.unimi.dsi.fastutil.objects.Reference2ObjectMaps; import net.kyori.adventure.key.Key; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3i; @@ -37,6 +34,8 @@ import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.level.block.Blocks; +import org.geysermc.geyser.level.block.property.BasicEnumProperty; +import org.geysermc.geyser.level.block.property.IntegerProperty; import org.geysermc.geyser.level.block.property.Property; import org.geysermc.geyser.level.physics.PistonBehavior; import org.geysermc.geyser.registry.BlockRegistries; @@ -67,6 +66,12 @@ public class Block { protected Item item = null; private int javaId = -1; + /** + * Used for switching a given block state to different states. + */ + private final Property[] propertyKeys; + private final BlockState defaultState; + public Block(@Subst("empty") String javaIdentifier, Builder builder) { this.javaIdentifier = Key.key(javaIdentifier); this.requiresCorrectToolForDrops = builder.requiresCorrectToolForDrops; @@ -74,7 +79,10 @@ public class Block { this.destroyTime = builder.destroyTime; this.pushReaction = builder.pushReaction; this.pickItem = builder.pickItem; - processStates(builder.build(this)); + + BlockState firstState = builder.build(this).get(0); + this.propertyKeys = builder.propertyKeys; // Ensure this is not null before iterating over states + this.defaultState = setDefaultState(firstState); } public void updateBlock(GeyserSession session, BlockState state, Vector3i position) { @@ -167,9 +175,11 @@ public class Block { } /** - * A list of BlockStates is created pertaining to this block. Do we need any of them? If so, override this method. + * Should only be ran on block creation. Can be overridden. + * @param firstState the first state created from this block */ - protected void processStates(List states) { + protected BlockState setDefaultState(BlockState firstState) { + return firstState; } @NonNull @@ -194,6 +204,10 @@ public class Block { return this.pushReaction; } + public BlockState defaultBlockState() { + return this.defaultState; + } + public int javaId() { return javaId; } @@ -213,6 +227,10 @@ public class Block { '}'; } + Property[] propertyKeys() { + return propertyKeys; + } + public static Builder builder() { return new Builder(); } @@ -225,11 +243,14 @@ public class Block { private float destroyTime; private Supplier pickItem; + // We'll use this field after building + private Property[] propertyKeys; + /** * For states that we're just tracking for mirroring Java states. */ - public Builder enumState(Property property, String... values) { - states.put(property, List.of(values)); + public Builder enumState(BasicEnumProperty property) { + states.put(property, property.values()); return this; } @@ -244,7 +265,9 @@ public class Block { return this; } - public Builder intState(Property property, int low, int high) { + public Builder intState(IntegerProperty property) { + int low = property.low(); + int high = property.high(); IntList list = new IntArrayList(); // There is a state for every number between the low and high. for (int i = low; i <= high; i++) { @@ -283,17 +306,18 @@ public class Block { if (states.isEmpty()) { BlockState state = new BlockState(block, BlockRegistries.BLOCK_STATES.get().size()); BlockRegistries.BLOCK_STATES.get().add(state); + propertyKeys = null; return List.of(state); } else if (states.size() == 1) { // We can optimize because we don't need to worry about combinations Map.Entry, List>> property = this.states.entrySet().stream().findFirst().orElseThrow(); List states = new ArrayList<>(property.getValue().size()); property.getValue().forEach(value -> { - Reference2ObjectMap, Comparable> propertyMap = Reference2ObjectMaps.singleton(property.getKey(), value); - BlockState state = new BlockState(block, BlockRegistries.BLOCK_STATES.get().size(), propertyMap); + BlockState state = new BlockState(block, BlockRegistries.BLOCK_STATES.get().size(), new Comparable[] {value}); BlockRegistries.BLOCK_STATES.get().add(state); states.add(state); }); + this.propertyKeys = new Property[]{property.getKey()}; return states; } else { // Think of this stream as another list containing, at the start, one empty list. @@ -327,11 +351,11 @@ public class Block { Property[] keys = this.states.keySet().toArray(new Property[0]); result.forEach(properties -> { Comparable[] values = properties.toArray(new Comparable[0]); - Reference2ObjectMap, Comparable> propertyMap = new Reference2ObjectArrayMap<>(keys, values); - BlockState state = new BlockState(block, BlockRegistries.BLOCK_STATES.get().size(), propertyMap); + BlockState state = new BlockState(block, BlockRegistries.BLOCK_STATES.get().size(), values); BlockRegistries.BLOCK_STATES.get().add(state); states.add(state); }); + this.propertyKeys = keys; return states; } } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java index 4fed30e7a..44271bd80 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java @@ -25,8 +25,7 @@ package org.geysermc.geyser.level.block.type; -import it.unimi.dsi.fastutil.objects.Reference2ObjectMap; -import it.unimi.dsi.fastutil.objects.Reference2ObjectMaps; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.level.block.property.Property; import org.geysermc.geyser.registry.BlockRegistries; @@ -35,13 +34,18 @@ import java.util.Locale; public final class BlockState { private final Block block; private final int javaId; - private final Reference2ObjectMap, Comparable> states; + /** + * The values of each property of this block state. These should be treated as keys to {@link Block#propertyKeys()} + * Of note - the comparable part probably doesn't do anything because we occasionally use strings in place of enums. + * Will be null if there's only one block state for a block. + */ + private final Comparable[] states; public BlockState(Block block, int javaId) { - this(block, javaId, Reference2ObjectMaps.emptyMap()); + this(block, javaId, null); } - BlockState(Block block, int javaId, Reference2ObjectMap, Comparable> states) { + BlockState(Block block, int javaId, Comparable[] states) { this.block = block; this.javaId = javaId; this.states = states; @@ -49,23 +53,97 @@ public final class BlockState { public > T getValue(Property property) { //noinspection unchecked - return (T) states.get(property); + return (T) get(property); } public boolean getValue(Property property, boolean def) { - var value = states.get(property); + var value = get(property); if (value == null) { return def; } return (Boolean) value; } + @Nullable + private Comparable get(Property property) { + Property[] keys = this.block.propertyKeys(); + if (keys == null) { + return null; + } + // We're copying the behavior Reference2ObjectArrayMap uses + for (int i = keys.length; i-- != 0;) { + if (keys[i] == property) { + return this.states[i]; + } + } + return null; + } + + /** + * @return the {@link BlockState} instance with the given value. + */ + public > BlockState withValue(Property property, T value) { + Property[] keys = this.block.propertyKeys(); + if (keys == null) { + throw new IllegalStateException(this + " does not have any different states!"); + } + + T currentValue = getValue(property); + if (currentValue == null) { + throw new IllegalArgumentException("This BlockState does not have the property " + property); + } + if (currentValue.equals(value)) { + // No action required. This block state is the state we're looking for. + return this; + } + + // Diff is how much we will have to traverse as a sort of offset + + // Block states are calculated in a predictable structure: + // minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=true,west=none] + // minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=true,west=low] + // minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=true,west=tall] + // minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=false,west=none] + // minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=false,west=low] + // minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=false,west=tall] + // minecraft:cobblestone_wall[east=none,north=none,south=none,up=false,waterlogged=true,west=none] + + // The last value goes through all its iterations, then the next state goes through all its iterations. + // West goes none -> low -> tall, then waterlogged is toggled as west cycles again. + // Then when waterlogged goes through all its properties, up is toggled, and west goes through again + // If we want to find the "up" property in order, then we need to find how many iterations each property + // after it goes in. West goes for 3, waterlogged goes for 2. Adding those together, we find that we need to + // add five to get to the next toggle of the up property + int diff = 0; + for (int i = keys.length - 1; i >= 0; i--) { + if (keys[i] != property) { + diff += keys[i].valuesCount(); + } else { + break; + } + } + + // How many times do we have to jump by diff? This depends on how far away each value is from each other. + // piston_head[facing=north] might be right next to piston_head[facing=south], which just one diff'd hop. + // But piston_head[facing=west] is further away, requiring more hops. + int thatOffset = property.indexOf(value); + int thisOffset = property.indexOf(currentValue); + if (diff == 0) { + // This can happen if the property is at the tail end of the block and there are no other properties to look through + // If we have minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=true,west=none] + // And want minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=true,west=low] + // The above for loop will always stop at the first break because the last property has already been found + diff = 1; + } + return BlockState.of(this.javaId + ((thatOffset - thisOffset) * diff)); + } + public Block block() { - return block; + return this.block; } public int javaId() { - return javaId; + return this.javaId; } public boolean is(Block block) { @@ -74,7 +152,7 @@ public final class BlockState { @Override public String toString() { - if (this.states.isEmpty()) { + if (this.states == null) { return this.block.javaIdentifier().toString(); } return this.block.javaIdentifier().toString() + "[" + paramsToString() + "]"; @@ -82,14 +160,15 @@ public final class BlockState { private String paramsToString() { StringBuilder builder = new StringBuilder(); - var it = this.states.entrySet().iterator(); - while (it.hasNext()) { - var entry = it.next(); - builder.append(entry.getKey().name()) - .append("=") - .append(entry.getValue().toString().toLowerCase(Locale.ROOT)); // lowercase covers enums - if (it.hasNext()) { - builder.append(","); + Property[] propertyKeys = this.block.propertyKeys(); + if (propertyKeys != null) { + for (int i = 0; i < propertyKeys.length; i++) { + builder.append(propertyKeys[i].name()) + .append("=") + .append(this.states[i].toString().toLowerCase(Locale.ROOT)); // lowercase covers enums + if (i < propertyKeys.length - 1) { + builder.append(","); + } } } return builder.toString(); diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/FurnaceBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/FurnaceBlock.java index 2b898e089..25d54ff2d 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/FurnaceBlock.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/FurnaceBlock.java @@ -28,29 +28,14 @@ package org.geysermc.geyser.level.block.type; import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.level.physics.Direction; -import java.util.List; - public class FurnaceBlock extends Block { - private static BlockState LIT; - private static BlockState UNLIT; - public FurnaceBlock(String javaIdentifier, Builder builder) { super(javaIdentifier, builder); } @Override - protected void processStates(List states) { - LIT = states.stream() - .filter(state -> state.getValue(Properties.HORIZONTAL_FACING) == Direction.NORTH - && state.getValue(Properties.LIT)) - .findFirst().orElseThrow(); - UNLIT = states.stream() - .filter(state -> state.getValue(Properties.HORIZONTAL_FACING) == Direction.NORTH - && !state.getValue(Properties.LIT)) - .findFirst().orElseThrow(); - } - - public static BlockState state(boolean lit) { - return lit ? LIT : UNLIT; + protected BlockState setDefaultState(BlockState firstState) { + // Both furnace minecart states look north. + return firstState.withValue(Properties.HORIZONTAL_FACING, Direction.NORTH); } } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/HoneyBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/HoneyBlock.java index 73c4d02aa..642240915 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/HoneyBlock.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/HoneyBlock.java @@ -25,21 +25,8 @@ package org.geysermc.geyser.level.block.type; -import java.util.List; - public class HoneyBlock extends Block { - private static BlockState STATE; - public HoneyBlock(String javaIdentifier, Builder builder) { super(javaIdentifier, builder); } - - @Override - protected void processStates(List states) { - STATE = states.get(0); - } - - public static BlockState state() { - return STATE; - } } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/SpawnerBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/SpawnerBlock.java index 2103fe6e5..968499d11 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/SpawnerBlock.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/SpawnerBlock.java @@ -25,21 +25,8 @@ package org.geysermc.geyser.level.block.type; -import java.util.List; - public class SpawnerBlock extends Block { - private static BlockState STATE; - public SpawnerBlock(String javaIdentifier, Builder builder) { super(javaIdentifier, builder); } - - @Override - protected void processStates(List states) { - STATE = states.get(0); - } - - public static BlockState state() { - return STATE; - } } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/WaterBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/WaterBlock.java index 801a7f9e7..9d2d23116 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/WaterBlock.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/WaterBlock.java @@ -25,17 +25,8 @@ package org.geysermc.geyser.level.block.type; -import java.util.List; - public class WaterBlock extends Block { - private static BlockState LEVEL_0; - public WaterBlock(String javaIdentifier, Builder builder) { super(javaIdentifier, builder); } - - @Override - protected void processStates(List states) { - super.processStates(states); - } } 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 ce89689eb..2be4e7a38 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 @@ -39,6 +39,9 @@ import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.player.PlayerEntity; import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.Blocks; +import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.PistonCache; import org.geysermc.geyser.translator.collision.BlockCollision; @@ -405,7 +408,8 @@ public class CollisionManager { * @return if the player is currently in a water block */ public boolean isPlayerInWater() { - return session.getGeyser().getWorldManager().getBlockAt(session, session.getPlayerEntity().getPosition().toInt()) == BlockStateValues.JAVA_WATER_ID; + BlockState state = session.getGeyser().getWorldManager().blockAt(session, session.getPlayerEntity().getPosition().toInt()); + return state.is(Blocks.WATER) && state.getValue(Properties.LEVEL) == 0; } public boolean isWaterInEyes() { 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 1d40386d4..6eadbd0e5 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 @@ -50,7 +50,6 @@ 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.item.Items; -import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.level.block.type.Block; @@ -433,25 +432,13 @@ public final class BlockRegistryPopulator { } int javaRuntimeId = -1; - int waterRuntimeId = -1; for (BlockState javaBlockState : BlockRegistries.BLOCK_STATES.get()) { javaRuntimeId++; String javaId = javaBlockState.toString().intern(); - BlockStateValues.storeBlockStateValues(javaId, javaRuntimeId); - BlockRegistries.JAVA_IDENTIFIER_TO_ID.register(javaId, javaRuntimeId); - - if ("minecraft:water[level=0]".equals(javaId)) { - waterRuntimeId = javaRuntimeId; - } } - if (waterRuntimeId == -1) { - throw new AssertionError("Unable to find Java water in palette"); - } - BlockStateValues.JAVA_WATER_ID = waterRuntimeId; - if (!BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().isEmpty()) { IntSet usedNonVanillaRuntimeIDs = new IntOpenHashSet(); 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 f618fde46..5c4e835e4 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 @@ -90,6 +90,10 @@ public class BlockMappings implements DefinitionRegistry { return this.getBedrockBlock(javaState.javaId()); } + public GeyserBedrockBlock getVanillaBedrockBlock(BlockState javaState) { + return getVanillaBedrockBlock(javaState.javaId()); + } + public GeyserBedrockBlock getVanillaBedrockBlock(int javaState) { if (javaState < 0 || javaState >= this.javaToVanillaBedrockBlocks.length) { return bedrockAir; diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/AbstractBlockInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/AbstractBlockInventoryTranslator.java index 2dfa2a85a..4476391c8 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/AbstractBlockInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/AbstractBlockInventoryTranslator.java @@ -31,6 +31,7 @@ import org.geysermc.geyser.inventory.holder.BlockInventoryHolder; import org.geysermc.geyser.inventory.holder.InventoryHolder; import org.geysermc.geyser.inventory.updater.InventoryUpdater; import org.geysermc.geyser.level.block.type.Block; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; /** @@ -40,17 +41,25 @@ public abstract class AbstractBlockInventoryTranslator extends BaseInventoryTran private final InventoryHolder holder; private final InventoryUpdater updater; + /** + * @param javaBlock a Java block that is used as a temporary block + */ + public AbstractBlockInventoryTranslator(int size, Block javaBlock, ContainerType containerType, InventoryUpdater updater, + Block... additionalValidBlocks) { + this(size, javaBlock.defaultBlockState(), containerType, updater, additionalValidBlocks); + } + /** * @param size the amount of slots that the inventory adds alongside the base inventory slots - * @param javaBlockIdentifier a Java block identifier that is used as a temporary block + * @param javaBlockState a Java block state that is used as a temporary block * @param containerType the container type of this inventory * @param updater updater * @param additionalValidBlocks any other blocks that can safely use this inventory without a fake block */ - public AbstractBlockInventoryTranslator(int size, String javaBlockIdentifier, ContainerType containerType, InventoryUpdater updater, + public AbstractBlockInventoryTranslator(int size, BlockState javaBlockState, ContainerType containerType, InventoryUpdater updater, Block... additionalValidBlocks) { super(size); - this.holder = new BlockInventoryHolder(javaBlockIdentifier, containerType, additionalValidBlocks); + this.holder = new BlockInventoryHolder(javaBlockState, containerType, additionalValidBlocks); this.updater = updater; } 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 705fac362..40ee28362 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 @@ -45,7 +45,7 @@ import java.util.Objects; public class AnvilInventoryTranslator extends AbstractBlockInventoryTranslator { public AnvilInventoryTranslator() { - super(3, "minecraft:anvil[facing=north]", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.ANVIL, AnvilInventoryUpdater.INSTANCE, + super(3, Blocks.ANVIL, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.ANVIL, AnvilInventoryUpdater.INSTANCE, Blocks.CHIPPED_ANVIL, Blocks.DAMAGED_ANVIL); } 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 9aeeff007..ceae1b640 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 @@ -27,7 +27,6 @@ package org.geysermc.geyser.translator.inventory; import it.unimi.dsi.fastutil.ints.IntSets; import org.cloudburstmc.math.vector.Vector3i; -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.ItemStackRequest; @@ -43,7 +42,9 @@ import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.PlayerInventory; import org.geysermc.geyser.inventory.holder.BlockInventoryHolder; import org.geysermc.geyser.inventory.updater.UIInventoryUpdater; +import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator; 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; @@ -52,7 +53,7 @@ import java.util.OptionalInt; public class BeaconInventoryTranslator extends AbstractBlockInventoryTranslator { public BeaconInventoryTranslator() { - super(1, new BlockInventoryHolder("minecraft:beacon", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.BEACON) { + super(1, new BlockInventoryHolder(Blocks.BEACON, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.BEACON) { @Override protected boolean checkInteractionPosition(GeyserSession session) { // Since we can't fall back to a virtual inventory, let's make opening one easier @@ -89,12 +90,8 @@ public class BeaconInventoryTranslator extends AbstractBlockInventoryTranslator // Send a block entity data packet update to the fake beacon inventory Vector3i position = inventory.getHolderPosition(); - NbtMapBuilder builder = NbtMap.builder() - .putInt("x", position.getX()) - .putInt("y", position.getY()) - .putInt("z", position.getZ()) + NbtMapBuilder builder = BlockEntityTranslator.getConstantBedrockTag("Beacon", position) .putString("CustomName", inventory.getTitle()) - .putString("id", "Beacon") .putInt("primary", beaconContainer.getPrimaryId()) .putInt("secondary", beaconContainer.getSecondaryId()); diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/BrewingInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/BrewingInventoryTranslator.java index a2c45384d..e425342f3 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/BrewingInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/BrewingInventoryTranslator.java @@ -32,11 +32,16 @@ import org.cloudburstmc.protocol.bedrock.packet.ContainerSetDataPacket; import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.updater.ContainerInventoryUpdater; +import org.geysermc.geyser.level.block.Blocks; +import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.session.GeyserSession; public class BrewingInventoryTranslator extends AbstractBlockInventoryTranslator { public BrewingInventoryTranslator() { - super(5, "minecraft:brewing_stand[has_bottle_0=false,has_bottle_1=false,has_bottle_2=false]", ContainerType.BREWING_STAND, ContainerInventoryUpdater.INSTANCE); + super(5, Blocks.BREWING_STAND.defaultBlockState() + .withValue(Properties.HAS_BOTTLE_0, false) + .withValue(Properties.HAS_BOTTLE_1, false) + .withValue(Properties.HAS_BOTTLE_2, false), ContainerType.BREWING_STAND, ContainerInventoryUpdater.INSTANCE); } @Override 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 a115bd953..b0914e5dd 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 @@ -30,12 +30,13 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemSt import org.geysermc.geyser.inventory.*; import org.geysermc.geyser.inventory.updater.UIInventoryUpdater; import org.geysermc.geyser.item.Items; +import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; public class CartographyInventoryTranslator extends AbstractBlockInventoryTranslator { public CartographyInventoryTranslator() { - super(3, "minecraft:cartography_table", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.CARTOGRAPHY, UIInventoryUpdater.INSTANCE); + super(3, Blocks.CARTOGRAPHY_TABLE, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.CARTOGRAPHY, UIInventoryUpdater.INSTANCE); } @Override 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 2a2f5beb5..8b0a0ac44 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 @@ -31,6 +31,7 @@ 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.CrafterInventoryUpdater; +import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.BlockEntityUtils; import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; @@ -53,7 +54,7 @@ public class CrafterInventoryTranslator extends AbstractBlockInventoryTranslator private static final int TRIGGERED = 1; // triggered value public CrafterInventoryTranslator() { - super(10, "minecraft:crafter", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.CRAFTER, CrafterInventoryUpdater.INSTANCE); + super(10, Blocks.CRAFTER, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.CRAFTER, CrafterInventoryUpdater.INSTANCE); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/CraftingInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/CraftingInventoryTranslator.java index 521db494a..4a0f1d7d9 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/CraftingInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/CraftingInventoryTranslator.java @@ -31,10 +31,11 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemSt import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.SlotType; import org.geysermc.geyser.inventory.updater.UIInventoryUpdater; +import org.geysermc.geyser.level.block.Blocks; public class CraftingInventoryTranslator extends AbstractBlockInventoryTranslator { public CraftingInventoryTranslator() { - super(10, "minecraft:crafting_table", ContainerType.WORKBENCH, UIInventoryUpdater.INSTANCE); + super(10, Blocks.CRAFTING_TABLE, ContainerType.WORKBENCH, UIInventoryUpdater.INSTANCE); } @Override 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 8fee2a391..e1407346a 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 @@ -38,6 +38,7 @@ import org.cloudburstmc.protocol.bedrock.packet.PlayerEnchantOptionsPacket; import org.geysermc.geyser.inventory.*; import org.geysermc.geyser.inventory.item.Enchantment; import org.geysermc.geyser.inventory.updater.UIInventoryUpdater; +import org.geysermc.geyser.level.block.Blocks; 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; @@ -47,7 +48,7 @@ import java.util.Locale; public class EnchantingInventoryTranslator extends AbstractBlockInventoryTranslator { public EnchantingInventoryTranslator() { - super(2, "minecraft:enchanting_table", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.ENCHANTMENT, UIInventoryUpdater.INSTANCE); + super(2, Blocks.ENCHANTING_TABLE, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.ENCHANTMENT, UIInventoryUpdater.INSTANCE); } @Override 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 f47a367d8..80040e375 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 @@ -41,7 +41,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; */ public class Generic3X3InventoryTranslator extends AbstractBlockInventoryTranslator { public Generic3X3InventoryTranslator() { - super(9, "minecraft:dispenser[facing=north,triggered=false]", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.DISPENSER, ContainerInventoryUpdater.INSTANCE, + super(9, Blocks.DISPENSER, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.DISPENSER, ContainerInventoryUpdater.INSTANCE, Blocks.DROPPER); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/GrindstoneInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/GrindstoneInventoryTranslator.java index a32b97b70..5344d27cb 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/GrindstoneInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/GrindstoneInventoryTranslator.java @@ -30,10 +30,11 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData; import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.updater.UIInventoryUpdater; +import org.geysermc.geyser.level.block.Blocks; public class GrindstoneInventoryTranslator extends AbstractBlockInventoryTranslator { public GrindstoneInventoryTranslator() { - super(3, "minecraft:grindstone[face=floor,facing=north]", ContainerType.GRINDSTONE, UIInventoryUpdater.INSTANCE); + super(3, Blocks.GRINDSTONE, ContainerType.GRINDSTONE, UIInventoryUpdater.INSTANCE); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/HopperInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/HopperInventoryTranslator.java index dab1ee972..fdcd7bf57 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/HopperInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/HopperInventoryTranslator.java @@ -29,13 +29,14 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.updater.ContainerInventoryUpdater; +import org.geysermc.geyser.level.block.Blocks; /** * Implemented on top of any block that does not have special properties implemented */ public class HopperInventoryTranslator extends AbstractBlockInventoryTranslator { public HopperInventoryTranslator() { - super(5, "minecraft:hopper[enabled=false,facing=down]", ContainerType.HOPPER, ContainerInventoryUpdater.INSTANCE); + super(5, Blocks.HOPPER, ContainerType.HOPPER, ContainerInventoryUpdater.INSTANCE); } @Override 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 f3bbc9b87..c6c3c7dd6 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 @@ -34,6 +34,7 @@ import org.geysermc.erosion.util.LecternUtils; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.*; import org.geysermc.geyser.inventory.updater.ContainerInventoryUpdater; +import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.BlockEntityUtils; @@ -56,7 +57,7 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator private boolean initialized = false; public LecternInventoryTranslator() { - super(1, "minecraft:lectern[facing=north,has_book=true,powered=true]", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.LECTERN , ContainerInventoryUpdater.INSTANCE); + super(1, Blocks.LECTERN, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.LECTERN , ContainerInventoryUpdater.INSTANCE); } @Override 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 e8571c8fb..0694e2ac6 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 @@ -45,6 +45,7 @@ import org.geysermc.geyser.inventory.SlotType; 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.level.block.Blocks; 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; @@ -101,7 +102,7 @@ public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator { } public LoomInventoryTranslator() { - super(4, "minecraft:loom[facing=north]", ContainerType.LOOM, UIInventoryUpdater.INSTANCE); + super(4, Blocks.LOOM, ContainerType.LOOM, UIInventoryUpdater.INSTANCE); } @Override 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 201c900d6..21fe9ca21 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 @@ -37,6 +37,7 @@ 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.level.block.Blocks; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.InventoryUtils; @@ -53,7 +54,7 @@ public class OldSmithingTableTranslator extends AbstractBlockInventoryTranslator private static final IntFunction UPGRADE_TEMPLATE = InventoryUtils.getUpgradeTemplate(); private OldSmithingTableTranslator() { - super(3, "minecraft:smithing_table", ContainerType.SMITHING_TABLE, UIInventoryUpdater.INSTANCE); + super(3, Blocks.SMITHING_TABLE, ContainerType.SMITHING_TABLE, UIInventoryUpdater.INSTANCE); } @Override 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 72f5260a0..464bf07f7 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 @@ -35,7 +35,10 @@ import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.holder.BlockInventoryHolder; import org.geysermc.geyser.inventory.updater.ContainerInventoryUpdater; +import org.geysermc.geyser.level.block.Blocks; +import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.level.block.type.BlockState; +import org.geysermc.geyser.level.physics.Direction; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator; @@ -43,12 +46,13 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType public class ShulkerInventoryTranslator extends AbstractBlockInventoryTranslator { public ShulkerInventoryTranslator() { - super(27, new BlockInventoryHolder("minecraft:shulker_box[facing=north]", ContainerType.CONTAINER) { + // Ensure that the shulker box default state won't be trying to open in a state facing the player + super(27, new BlockInventoryHolder(Blocks.SHULKER_BOX.defaultBlockState().withValue(Properties.FACING, Direction.NORTH), ContainerType.CONTAINER) { private final BlockEntityTranslator shulkerBoxTranslator = Registries.BLOCK_ENTITIES.get(BlockEntityType.SHULKER_BOX); @Override - protected boolean isValidBlock(String[] javaBlockString) { - return javaBlockString[0].contains("shulker_box"); + protected boolean isValidBlock(BlockState blockState) { + return blockState.block().javaIdentifier().value().contains("shulker_box"); // TODO ew } @Override diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/SmithingInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/SmithingInventoryTranslator.java index 730e4a451..c68347fd3 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/SmithingInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/SmithingInventoryTranslator.java @@ -30,10 +30,11 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData; import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.updater.UIInventoryUpdater; +import org.geysermc.geyser.level.block.Blocks; public class SmithingInventoryTranslator extends AbstractBlockInventoryTranslator { public SmithingInventoryTranslator() { - super(4, "minecraft:smithing_table", ContainerType.SMITHING_TABLE, UIInventoryUpdater.INSTANCE); + super(4, Blocks.SMITHING_TABLE, ContainerType.SMITHING_TABLE, UIInventoryUpdater.INSTANCE); } @Override 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 54f2f447b..b977ee1a1 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 @@ -35,6 +35,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemS import org.geysermc.geyser.inventory.*; import org.geysermc.geyser.inventory.recipe.GeyserStonecutterData; import org.geysermc.geyser.inventory.updater.UIInventoryUpdater; +import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; @@ -42,7 +43,7 @@ import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.S public class StonecutterInventoryTranslator extends AbstractBlockInventoryTranslator { public StonecutterInventoryTranslator() { - super(2, "minecraft:stonecutter[facing=north]", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.STONECUTTER, UIInventoryUpdater.INSTANCE); + super(2, Blocks.STONECUTTER, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.STONECUTTER, UIInventoryUpdater.INSTANCE); } @Override 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 4c49c8e5a..4bc727397 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 @@ -40,6 +40,7 @@ import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.level.block.property.ChestType; import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.level.block.type.BlockState; +import org.geysermc.geyser.level.physics.Direction; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator; @@ -51,7 +52,10 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator { public DoubleChestInventoryTranslator(int size) { super(size, 54); - this.defaultJavaBlockState = BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getInt("minecraft:chest[facing=north,type=single,waterlogged=false]"); + this.defaultJavaBlockState = Blocks.CHEST.defaultBlockState() + .withValue(Properties.HORIZONTAL_FACING, Direction.NORTH) + .withValue(Properties.CHEST_TYPE, ChestType.SINGLE) + .javaId(); } @Override @@ -96,11 +100,7 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator { blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY); session.sendUpstreamPacket(blockPacket); - NbtMap tag = NbtMap.builder() - .putString("id", "Chest") - .putInt("x", position.getX()) - .putInt("y", position.getY()) - .putInt("z", position.getZ()) + NbtMap tag = BlockEntityTranslator.getConstantBedrockTag("Chest", position) .putInt("pairx", pairPosition.getX()) .putInt("pairz", pairPosition.getZ()) .putString("CustomName", inventory.getTitle()).build(); diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/chest/SingleChestInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/chest/SingleChestInventoryTranslator.java index e18096862..264b2eb29 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/chest/SingleChestInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/chest/SingleChestInventoryTranslator.java @@ -30,6 +30,9 @@ import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.holder.BlockInventoryHolder; import org.geysermc.geyser.inventory.holder.InventoryHolder; import org.geysermc.geyser.level.block.Blocks; +import org.geysermc.geyser.level.block.property.ChestType; +import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; public class SingleChestInventoryTranslator extends ChestInventoryTranslator { @@ -38,17 +41,17 @@ public class SingleChestInventoryTranslator extends ChestInventoryTranslator { // TODO add barrel??? public SingleChestInventoryTranslator(int size) { super(size, 27); - this.holder = new BlockInventoryHolder("minecraft:chest[facing=north,type=single,waterlogged=false]", ContainerType.CONTAINER, + this.holder = new BlockInventoryHolder(Blocks.CHEST.defaultBlockState().withValue(Properties.CHEST_TYPE, ChestType.SINGLE), ContainerType.CONTAINER, Blocks.ENDER_CHEST, Blocks.TRAPPED_CHEST) { @Override - protected boolean isValidBlock(String[] javaBlockString) { - if (javaBlockString[0].equals("minecraft:ender_chest")) { + protected boolean isValidBlock(BlockState blockState) { + if (blockState.is(Blocks.ENDER_CHEST)) { // Can't have double ender chests return true; } // Add provision to ensure this isn't a double chest - return super.isValidBlock(javaBlockString) && (javaBlockString.length > 1 && javaBlockString[1].contains("type=single")); + return super.isValidBlock(blockState) && blockState.getValue(Properties.CHEST_TYPE) == ChestType.SINGLE; } }; } diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/AbstractFurnaceInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/AbstractFurnaceInventoryTranslator.java index 6cda03a19..8991ef787 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/AbstractFurnaceInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/AbstractFurnaceInventoryTranslator.java @@ -32,12 +32,14 @@ import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.SlotType; import org.geysermc.geyser.inventory.updater.ContainerInventoryUpdater; +import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.inventory.AbstractBlockInventoryTranslator; public abstract class AbstractFurnaceInventoryTranslator extends AbstractBlockInventoryTranslator { - AbstractFurnaceInventoryTranslator(String javaBlockIdentifier, ContainerType containerType) { - super(3, javaBlockIdentifier, containerType, ContainerInventoryUpdater.INSTANCE); + AbstractFurnaceInventoryTranslator(Block javaBlock, ContainerType containerType) { + super(3, javaBlock.defaultBlockState().withValue(Properties.LIT, false), containerType, ContainerInventoryUpdater.INSTANCE); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/BlastFurnaceInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/BlastFurnaceInventoryTranslator.java index 0b6e0c674..185cafc51 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/BlastFurnaceInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/BlastFurnaceInventoryTranslator.java @@ -28,10 +28,11 @@ package org.geysermc.geyser.translator.inventory.furnace; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.geysermc.geyser.inventory.BedrockContainerSlot; +import org.geysermc.geyser.level.block.Blocks; public class BlastFurnaceInventoryTranslator extends AbstractFurnaceInventoryTranslator { public BlastFurnaceInventoryTranslator() { - super("minecraft:blast_furnace[facing=north,lit=false]", ContainerType.BLAST_FURNACE); + super(Blocks.BLAST_FURNACE, ContainerType.BLAST_FURNACE); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/FurnaceInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/FurnaceInventoryTranslator.java index 95a79a93e..bc96f7105 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/FurnaceInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/FurnaceInventoryTranslator.java @@ -28,10 +28,11 @@ package org.geysermc.geyser.translator.inventory.furnace; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.geysermc.geyser.inventory.BedrockContainerSlot; +import org.geysermc.geyser.level.block.Blocks; public class FurnaceInventoryTranslator extends AbstractFurnaceInventoryTranslator { public FurnaceInventoryTranslator() { - super("minecraft:furnace[facing=north,lit=false]", ContainerType.FURNACE); + super(Blocks.FURNACE, ContainerType.FURNACE); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/SmokerInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/SmokerInventoryTranslator.java index 2f87f3b13..380446f09 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/SmokerInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/furnace/SmokerInventoryTranslator.java @@ -28,10 +28,11 @@ package org.geysermc.geyser.translator.inventory.furnace; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.geysermc.geyser.inventory.BedrockContainerSlot; +import org.geysermc.geyser.level.block.Blocks; public class SmokerInventoryTranslator extends AbstractFurnaceInventoryTranslator { public SmokerInventoryTranslator() { - super("minecraft:smoker[facing=north,lit=false]", ContainerType.SMOKER); + super(Blocks.SMOKER, ContainerType.SMOKER); } @Override 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 ca8679319..350ce8c3e 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 @@ -26,22 +26,24 @@ package org.geysermc.geyser.translator.level.block.entity; import it.unimi.dsi.fastutil.ints.IntArrays; -import it.unimi.dsi.fastutil.objects.*; -import org.geysermc.geyser.level.block.Blocks; -import org.geysermc.geyser.level.block.type.Block; -import org.geysermc.geyser.level.block.type.BlockState; -import org.geysermc.geyser.level.block.type.HoneyBlock; -import org.geysermc.geyser.level.block.type.PistonBlock; -import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectMaps; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import lombok.Getter; import org.cloudburstmc.math.vector.Vector3d; 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.packet.UpdateBlockPacket; -import lombok.Getter; import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.Blocks; +import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.geyser.level.block.type.Block; +import org.geysermc.geyser.level.block.type.BlockState; +import org.geysermc.geyser.level.block.type.PistonBlock; import org.geysermc.geyser.level.physics.Axis; import org.geysermc.geyser.level.physics.BoundingBox; import org.geysermc.geyser.level.physics.CollisionManager; @@ -53,6 +55,7 @@ import org.geysermc.geyser.translator.collision.BlockCollision; import org.geysermc.geyser.util.BlockEntityUtils; import org.geysermc.geyser.util.BlockUtils; import org.geysermc.geyser.util.ChunkUtils; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType; import java.util.LinkedList; import java.util.Map; @@ -99,7 +102,7 @@ public class PistonBlockEntity { static { // Create a ~1 x ~0.5 x ~1 bounding box above the honey block - BlockCollision blockCollision = BlockRegistries.COLLISIONS.get(HoneyBlock.state().javaId()); + BlockCollision blockCollision = BlockRegistries.COLLISIONS.get(Blocks.HONEY_BLOCK.defaultBlockState().javaId()); if (blockCollision == null) { throw new RuntimeException("Failed to find honey block collision"); } @@ -224,10 +227,10 @@ public class PistonBlockEntity { private void removePistonHead() { Vector3i blockInFront = position.add(orientation.getUnitVector()); - int blockId = session.getGeyser().getWorldManager().getBlockAt(session, blockInFront); - if (BlockStateValues.isPistonHead(blockId)) { + BlockState state = session.getGeyser().getWorldManager().blockAt(session, blockInFront); + if (state.is(Blocks.PISTON_HEAD)) { ChunkUtils.updateBlock(session, Block.JAVA_AIR_ID, blockInFront); - } else if ((session.getGeyser().getPlatformType() == PlatformType.SPIGOT || session.getErosionHandler().isActive()) && blockId == Block.JAVA_AIR_ID) { + } else if ((session.getGeyser().getPlatformType() == PlatformType.SPIGOT || session.getErosionHandler().isActive()) && state.is(Blocks.AIR)) { // Spigot removes the piston head from the cache, but we need to send the block update ourselves ChunkUtils.updateBlock(session, Block.JAVA_AIR_ID, blockInFront); } @@ -353,7 +356,9 @@ public class PistonBlockEntity { playerBoundingBox.setSizeZ(playerBoundingBox.getSizeZ() - shrink.getZ()); // Resolve collision with the piston head - BlockState pistonHeadId = BlockState.of(BlockStateValues.getPistonHead(orientation)); + BlockState pistonHeadId = Blocks.PISTON_HEAD.defaultBlockState() + .withValue(Properties.SHORT, false) + .withValue(Properties.FACING, orientation); pushPlayerBlock(pistonHeadId, getPistonHeadPos().toDouble(), blockMovement, playerBoundingBox); // Resolve collision with any attached moving blocks, but skip slime blocks @@ -562,9 +567,11 @@ public class PistonBlockEntity { private BlockState getAttachedBlockId(Vector3i blockPos) { if (blockPos.equals(getPistonHeadPos())) { - return BlockState.of(BlockStateValues.getPistonHead(orientation)); + return Blocks.PISTON_HEAD.defaultBlockState() + .withValue(Properties.SHORT, false) + .withValue(Properties.FACING, orientation); } else { - return attachedBlocks.getOrDefault(blockPos, BlockState.of(Block.JAVA_AIR_ID)); //FIXME + return attachedBlocks.getOrDefault(blockPos, Blocks.AIR.defaultBlockState()); } } @@ -633,7 +640,9 @@ public class PistonBlockEntity { if (action == PistonValueType.PUSHING) { Vector3i pistonHeadPos = getPistonHeadPos().add(movement); if (!SOLID_BOUNDING_BOX.checkIntersection(pistonHeadPos.toDouble(), session.getCollisionManager().getPlayerBoundingBox())) { - ChunkUtils.updateBlock(session, BlockStateValues.getPistonHead(orientation), pistonHeadPos); + ChunkUtils.updateBlock(session, Blocks.PISTON_HEAD.defaultBlockState() + .withValue(Properties.SHORT, false) + .withValue(Properties.FACING, orientation), pistonHeadPos); } } } 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 25f9f5497..878d326ac 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 @@ -56,8 +56,8 @@ import org.geysermc.geyser.item.type.BlockItem; import org.geysermc.geyser.item.type.BoatItem; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.item.type.SpawnEggItem; -import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.Blocks; +import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.level.block.type.CauldronBlock; @@ -295,10 +295,10 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator { - private static final String[] ALL_BLOCK_NAMES = BlockRegistries.JAVA_BLOCKS.get().stream().map(block -> block.javaIdentifier().toString()).toArray(String[]::new); + /** + * Wait until the registries load before getting all the block names. + */ + private static final Supplier ALL_BLOCK_NAMES = Suppliers.memoize(() -> BlockRegistries.JAVA_BLOCKS.get().stream().map(block -> block.javaIdentifier().toString()).toArray(String[]::new)); private static final String[] ALL_EFFECT_IDENTIFIERS = EntityUtils.getAllEffectIdentifiers(); 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"}; @@ -247,7 +252,7 @@ public class JavaCommandsTranslator extends PacketTranslator CommandParam.FILE_PATH; case BOOL -> ENUM_BOOLEAN; case OPERATION -> CommandParam.OPERATOR; // ">=", "==", etc - case BLOCK_STATE -> ALL_BLOCK_NAMES; + case BLOCK_STATE -> ALL_BLOCK_NAMES.get(); case ITEM_STACK -> context.getItemNames(); case COLOR -> VALID_COLORS; case SCOREBOARD_SLOT -> VALID_SCOREBOARD_SLOTS; diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3a3a2d20c..aa68a0bc0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -65,7 +65,6 @@ fastutil-int-byte-maps = { group = "com.nukkitx.fastutil", name = "fastutil-int- fastutil-int-boolean-maps = { group = "com.nukkitx.fastutil", name = "fastutil-int-boolean-maps", version.ref = "fastutil" } fastutil-object-int-maps = { group = "com.nukkitx.fastutil", name = "fastutil-object-int-maps", version.ref = "fastutil" } fastutil-object-object-maps = { group = "com.nukkitx.fastutil", name = "fastutil-object-object-maps", version.ref = "fastutil" } -fastutil-reference-object-maps = { group = "com.nukkitx.fastutil", name = "fastutil-reference-object-maps", version.ref = "fastutil" } adventure-text-serializer-gson = { group = "net.kyori", name = "adventure-text-serializer-gson", version.ref = "adventure" } # Remove when we remove our Adventure bump adventure-text-serializer-legacy = { group = "net.kyori", name = "adventure-text-serializer-legacy", version.ref = "adventure" } @@ -143,7 +142,7 @@ 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", "fastutil-reference-object-maps" ] +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-slf4j2-impl" ] jline = [ "jline-terminal", "jline-terminal-jna", "jline-reader" ] From 96bfda2ed3f53a90266876b8b8741d2052dfa8ef Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 21 May 2024 20:37:18 -0400 Subject: [PATCH 026/233] Fix #4683 --- .../geyser/session/cache/LodestoneCache.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) 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 50cdf4b5b..f66daf027 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 @@ -28,7 +28,6 @@ package org.geysermc.geyser.session.cache; 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; @@ -53,11 +52,13 @@ public final class LodestoneCache { private int id = 1; public void cacheInventoryItem(GeyserItemStack itemStack, LodestoneTracker tracker) { - GlobalPos position = tracker.getPos(); + if (!tracker.isTracked()) { + return; + } + GlobalPos position = tracker.getPos(); if (position == null) { - GeyserImpl.getInstance().getLogger().error("Position is null. Find out why."); - Thread.dumpStack(); + // As of 1.20.6, position can still be null even if tracking is enabled. return; } int x = position.getX(); @@ -84,13 +85,16 @@ public final class LodestoneCache { } public int store(LodestoneTracker tracker) { - GlobalPos position = tracker.getPos(); - - if (position == null) { - GeyserImpl.getInstance().getLogger().error("Position is null. Find out why."); - Thread.dumpStack(); - return -1; + if (!tracker.isTracked()) { + // No coordinates; nothing to convert + return 0; } + + GlobalPos position = tracker.getPos(); + if (position == null) { + return 0; + } + int x = position.getX(); int y = position.getY(); int z = position.getZ(); From f7b026d61b7f07459542928bdd3766843724a43b Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 21 May 2024 20:56:13 -0400 Subject: [PATCH 027/233] Remove old sneaking/crawling workarounds Since Bedrock implements these natively, there's no need for extra checks. :) --- .../type/player/SessionPlayerEntity.java | 34 ----------- .../geyser/session/GeyserSession.java | 58 ++----------------- 2 files changed, 4 insertions(+), 88 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 e10adb134..ca541b5d3 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 @@ -31,7 +31,6 @@ 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; -import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; import org.geysermc.geyser.entity.attribute.GeyserAttributeType; import org.geysermc.geyser.item.Items; @@ -60,10 +59,6 @@ public class SessionPlayerEntity extends PlayerEntity { */ @Getter protected final Map attributes = new Object2ObjectOpenHashMap<>(); - /** - * Whether to check for updated speed after all entity metadata has been processed - */ - private boolean refreshSpeed = false; /** * Used in PlayerInputTranslator for movement checks. */ @@ -120,9 +115,7 @@ public class SessionPlayerEntity extends PlayerEntity { // 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; } /** @@ -150,7 +143,6 @@ public class SessionPlayerEntity extends PlayerEntity { public void setPose(Pose pose) { super.setPose(pose); session.setPose(pose); - refreshSpeed = true; } public float getMaxHealth() { @@ -199,21 +191,6 @@ public class SessionPlayerEntity extends PlayerEntity { } } - @Override - public void updateBedrockMetadata() { - super.updateBedrockMetadata(); - if (refreshSpeed) { - AttributeData speedAttribute = session.adjustSpeed(); - if (speedAttribute != null) { - UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket(); - attributesPacket.setRuntimeEntityId(geyserId); - attributesPacket.setAttributes(Collections.singletonList(speedAttribute)); - session.sendUpstreamPacket(attributesPacket); - } - refreshSpeed = false; - } - } - @Override protected void updateAttribute(Attribute javaAttribute, List newAttributes) { if (javaAttribute.getType() == AttributeType.Builtin.GENERIC_ATTACK_SPEED) { @@ -226,17 +203,6 @@ public class SessionPlayerEntity extends PlayerEntity { @Override protected AttributeData calculateAttribute(Attribute javaAttribute, GeyserAttributeType type) { AttributeData attributeData = super.calculateAttribute(javaAttribute, type); - - if (javaAttribute.getType() == AttributeType.Builtin.GENERIC_MOVEMENT_SPEED) { - session.setOriginalSpeedAttribute(attributeData.getValue()); - AttributeData speedAttribute = session.adjustSpeed(); - if (speedAttribute != null) { - // Overwrite the attribute with our own - this.attributes.put(type, speedAttribute); - return speedAttribute; - } - } - this.attributes.put(type, attributeData); return attributeData; } 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 c85c0fd28..aa256df55 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -317,22 +317,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Setter private boolean sprinting; - /** - * Whether the player is swimming in water. - * Used to update speed when crawling. - */ - @Setter - private boolean swimmingInWater; - - /** - * 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. - */ - @Setter - private float originalSpeedAttribute; - /** * The dimension of the player. * As all entities are in the same world, this can be safely applied to all other entities. @@ -1283,21 +1267,11 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { this.sneaking = sneaking; // Update pose and bounding box on our end - AttributeData speedAttribute; - if (!sneaking && (speedAttribute = adjustSpeed()) != null) { - // Update attributes since we're still "sneaking" under a 1.5-block-tall area - UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket(); - attributesPacket.setRuntimeEntityId(playerEntity.getGeyserId()); - attributesPacket.setAttributes(Collections.singletonList(speedAttribute)); - sendUpstreamPacket(attributesPacket); - // the server *should* update our pose once it has returned to normal - } else { - if (!flying) { - // The pose and bounding box should not be updated if the player is flying - setSneakingPose(sneaking); - } - collisionManager.updateScaffoldingFlags(false); + if (!flying) { + // The pose and bounding box should not be updated if the player is flying + setSneakingPose(sneaking); } + collisionManager.updateScaffoldingFlags(false); playerEntity.updateBedrockMetadata(); @@ -1340,30 +1314,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { } } - /** - * Adjusts speed if the player is crawling. - * - * @return not null if attributes should be updated. - */ - public @Nullable AttributeData adjustSpeed() { - AttributeData currentPlayerSpeed = playerEntity.getAttributes().get(GeyserAttributeType.MOVEMENT_SPEED); - if (currentPlayerSpeed != null) { - if ((pose.equals(Pose.SNEAKING) && !sneaking && collisionManager.mustPlayerSneakHere()) || - (!swimmingInWater && playerEntity.getFlag(EntityFlag.SWIMMING) && !collisionManager.isPlayerInWater())) { - // Either of those conditions means that Bedrock goes zoom when they shouldn't be - AttributeData speedAttribute = GeyserAttributeType.MOVEMENT_SPEED.getAttribute(originalSpeedAttribute / 3.32f); - playerEntity.getAttributes().put(GeyserAttributeType.MOVEMENT_SPEED, speedAttribute); - return speedAttribute; - } else if (originalSpeedAttribute != currentPlayerSpeed.getValue()) { - // Speed has reset to normal - AttributeData speedAttribute = GeyserAttributeType.MOVEMENT_SPEED.getAttribute(originalSpeedAttribute); - playerEntity.getAttributes().put(GeyserAttributeType.MOVEMENT_SPEED, speedAttribute); - return speedAttribute; - } - } - return null; - } - /** * Checks to see if a shield is in either hand to activate blocking. If so, it sets the Bedrock client to display * blocking and sends a packet to the Java server. From 6f4c29c834b4f111ee9807da89fc3aa83d93c83d Mon Sep 17 00:00:00 2001 From: gecko10000 <60494179+gecko10000@users.noreply.github.com> Date: Wed, 22 May 2024 02:26:32 -0700 Subject: [PATCH 028/233] Match Advancement Packet Behavior Towards Java (#4684) * Send advancement packet regardless of current tab * Send advancement close packet when single-advancement form closed --- .../geyser/session/cache/AdvancementsCache.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) 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 6769b4330..be1eb3a5b 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 @@ -91,11 +91,9 @@ public class AdvancementsCache { builder.validResultHandler((response) -> { String id = rootAdvancementIds.get(response.clickedButtonId()); if (!id.equals("")) { - if (!id.equals(currentAdvancementCategoryId)) { - // Send a packet indicating that we are opening this particular advancement window - ServerboundSeenAdvancementsPacket packet = new ServerboundSeenAdvancementsPacket(id); - session.sendDownstreamGamePacket(packet); - } + // Send a packet indicating that we are opening this particular advancement window + ServerboundSeenAdvancementsPacket packet = new ServerboundSeenAdvancementsPacket(id); + session.sendDownstreamGamePacket(packet); currentAdvancementCategoryId = id; buildAndShowListForm(); } @@ -188,6 +186,10 @@ public class AdvancementsCache { .content(content) .button(GeyserLocale.getPlayerLocaleString("gui.back", language)) .validResultHandler((response) -> buildAndShowListForm()) + .closedResultHandler(() -> { + // Indicate that we have closed the current advancement tab + session.sendDownstreamGamePacket(new ServerboundSeenAdvancementsPacket()); + }) ); } From ec3327efebd017f43966299f5b6a528128ea2f50 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Thu, 23 May 2024 11:41:26 -0400 Subject: [PATCH 029/233] Minor minor changes --- .../geyser/level/block/property/BasicEnumProperty.java | 2 +- .../java/org/geysermc/geyser/level/block/type/BlockState.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/level/block/property/BasicEnumProperty.java b/core/src/main/java/org/geysermc/geyser/level/block/property/BasicEnumProperty.java index f55b85d7b..c34392504 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/property/BasicEnumProperty.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/property/BasicEnumProperty.java @@ -47,7 +47,7 @@ public final class BasicEnumProperty extends Property { public int indexOf(String value) { int index = this.values.indexOf(value); if (index == -1) { - throw new IllegalStateException("Property " + this + " does not have value " + value); + throw new IllegalArgumentException("Property " + this + " does not have value " + value); } return index; } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java index 44271bd80..a312a7d5a 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java @@ -35,7 +35,7 @@ public final class BlockState { private final Block block; private final int javaId; /** - * The values of each property of this block state. These should be treated as keys to {@link Block#propertyKeys()} + * The values of each property of this block state. These should be treated as keys to {@link Block#propertyKeys()}. * Of note - the comparable part probably doesn't do anything because we occasionally use strings in place of enums. * Will be null if there's only one block state for a block. */ @@ -135,7 +135,7 @@ public final class BlockState { // The above for loop will always stop at the first break because the last property has already been found diff = 1; } - return BlockState.of(this.javaId + ((thatOffset - thisOffset) * diff)); + return of(this.javaId + ((thatOffset - thisOffset) * diff)); } public Block block() { From d5fdbeb49c5b304aa18070ae4abae1e3d0f36763 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Sat, 25 May 2024 13:19:59 +0100 Subject: [PATCH 030/233] Make allow-third-party-capes default to false (#4690) --- .../geyser/configuration/GeyserJacksonConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 a55e4af8f..81ac824e4 100644 --- a/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java +++ b/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java @@ -94,7 +94,7 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration private boolean debugMode = false; @JsonProperty("allow-third-party-capes") - private boolean allowThirdPartyCapes = true; + private boolean allowThirdPartyCapes = false; @JsonProperty("show-cooldown") private String showCooldown = "title"; From 0ea01bfa4876fd9722698f096dbbfefbf5ccd7d1 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sat, 25 May 2024 18:59:37 -0400 Subject: [PATCH 031/233] Allow skull pick item NBT --- .../geyser/inventory/GeyserItemStack.java | 2 +- .../geyser/level/block/type/SkullBlock.java | 36 +++++++++++++++++++ .../BedrockBlockPickRequestTranslator.java | 7 +++- 3 files changed, 43 insertions(+), 2 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 fa62769fe..744ad70b6 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java @@ -69,7 +69,7 @@ public class GeyserItemStack { return of(javaId, amount, null); } - public static @NonNull GeyserItemStack of(int javaId, int amount, DataComponents components) { + public static @NonNull GeyserItemStack of(int javaId, int amount, @Nullable DataComponents components) { return new GeyserItemStack(javaId, amount, components); } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/SkullBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/SkullBlock.java index 76b532919..c4aae46a2 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/SkullBlock.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/SkullBlock.java @@ -25,10 +25,20 @@ package org.geysermc.geyser.level.block.type; +import com.github.steveice10.mc.auth.data.GameProfile; import org.cloudburstmc.math.vector.Vector3i; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; +import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.SkullCache; +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.Collections; +import java.util.UUID; public class SkullBlock extends Block { private final Type type; @@ -55,6 +65,32 @@ public class SkullBlock extends Block { // It's not an empty skull. } + public ItemStack pickItem(GeyserSession session, BlockState state, Vector3i position) { + SkullCache.Skull skull = session.getSkullCache().getSkulls().get(position); + if (skull == null) { + return new ItemStack(pickItem(state).getId()); + } + + GeyserItemStack itemStack = GeyserItemStack.of(pickItem(state).getId(), 1); + // This is a universal block entity behavior, but hardcode how it works for now. + NbtMapBuilder builder = NbtMap.builder() + .putString("id", "minecraft:skull") + .putInt("x", position.getX()) + .putInt("y", position.getY()) + .putInt("z", position.getZ()); + DataComponents components = itemStack.getOrCreateComponents(); + components.put(DataComponentType.BLOCK_ENTITY_DATA, builder.build()); + + UUID uuid = skull.getUuid(); + String texturesProperty = skull.getTexturesProperty(); + GameProfile profile = new GameProfile(uuid, null); + if (texturesProperty != null) { + profile.setProperties(Collections.singletonList(new GameProfile.Property("textures", texturesProperty))); + } + components.put(DataComponentType.PROFILE, profile); + return itemStack.getItemStack(); + } + public Type skullType() { return type; } 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 0a721e4b0..94368a6d4 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 @@ -33,6 +33,7 @@ import org.geysermc.geyser.item.Items; import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.level.block.type.BannerBlock; import org.geysermc.geyser.level.block.type.BlockState; +import org.geysermc.geyser.level.block.type.SkullBlock; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; @@ -65,7 +66,11 @@ public class BedrockBlockPickRequestTranslator extends PacketTranslator session.ensureInEventLoop(() -> { if (components == null) { From 5f7a31a1d837048a147258f3caf2f750c7738fb7 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sat, 25 May 2024 20:55:05 -0400 Subject: [PATCH 032/233] Fix #4688 --- .../org/geysermc/geyser/entity/type/InteractionEntity.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 4e7a805b4..06035a47c 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 @@ -80,7 +80,10 @@ public class InteractionEntity extends Entity { } public void setHeight(FloatEntityMetadata height) { - setBoundingBoxHeight(height.getPrimitiveValue()); + // Bedrock does *not* like high values being placed here + // https://gist.github.com/Owen1212055/f5d59169d3a6a5c32f0c173d57eb199d recommend(s/ed) using the tactic + // https://github.com/GeyserMC/Geyser/issues/4688 + setBoundingBoxHeight(Math.min(height.getPrimitiveValue(), 64f)); } public void setResponse(BooleanEntityMetadata response) { From fa6808a62029373af4492329bbf2cbf80bb51e7f Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Sun, 26 May 2024 20:00:47 -0700 Subject: [PATCH 033/233] Bedrock 1.21.0 Support (#4687) * 1.21.0 Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Deprecate Bedrock 1.20.70 and below Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Strictly disconnect on all exceptions Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> * Remove old version resources 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 +- .../holder/BlockInventoryHolder.java | 1 + .../geyser/network/CodecProcessor.java | 23 +- .../geysermc/geyser/network/GameProtocol.java | 36 +- .../geyser/network/InvalidPacketHandler.java | 4 +- .../populator/BlockRegistryPopulator.java | 13 +- .../registry/populator/Conversion630_622.java | 217 - .../registry/populator/Conversion649_630.java | 64 - .../registry/populator/Conversion662_649.java | 187 - .../registry/populator/Conversion671_662.java | 205 - .../registry/populator/Conversion685_671.java | 205 + .../CustomBlockRegistryPopulator.java | 9 +- .../CustomItemRegistryPopulator.java | 118 +- .../populator/ItemRegistryPopulator.java | 30 +- .../populator/RecipeRegistryPopulator.java | 5 +- .../geyser/session/GeyserSession.java | 4 + .../inventory/LecternInventoryTranslator.java | 19 - .../inventory/PlayerInventoryTranslator.java | 1 + .../chest/DoubleChestInventoryTranslator.java | 1 + .../player/BedrockActionTranslator.java | 5 - .../java/JavaUpdateRecipesTranslator.java | 7 +- .../JavaContainerSetSlotTranslator.java | 4 +- .../inventory/JavaOpenBookTranslator.java | 6 - .../inventory/JavaOpenScreenTranslator.java | 6 - .../bedrock/block_palette.1_20_40.nbt | Bin 158101 -> 0 bytes .../bedrock/block_palette.1_20_50.nbt | Bin 170466 -> 0 bytes .../bedrock/block_palette.1_20_60.nbt | Bin 124510 -> 0 bytes .../bedrock/block_palette.1_20_70.nbt | Bin 176502 -> 0 bytes .../bedrock/block_palette.1_21_0.nbt | Bin 0 -> 177397 bytes .../bedrock/creative_items.1_20_40.json | 5787 ---------------- .../bedrock/creative_items.1_20_50.json | 5995 ---------------- .../bedrock/creative_items.1_20_60.json | 5787 ---------------- ..._20_70.json => creative_items.1_21_0.json} | 2033 +++--- .../resources/bedrock/entity_identifiers.dat | Bin 7951 -> 8314 bytes .../bedrock/runtime_item_states.1_20_40.json | 5570 --------------- .../bedrock/runtime_item_states.1_20_50.json | 5846 ---------------- .../bedrock/runtime_item_states.1_20_60.json | 5998 ----------------- ...0.json => runtime_item_states.1_21_0.json} | 1300 ++-- core/src/main/resources/mappings | 2 +- gradle/libs.versions.toml | 12 +- 40 files changed, 2325 insertions(+), 37177 deletions(-) delete mode 100644 core/src/main/java/org/geysermc/geyser/registry/populator/Conversion630_622.java delete mode 100644 core/src/main/java/org/geysermc/geyser/registry/populator/Conversion649_630.java delete mode 100644 core/src/main/java/org/geysermc/geyser/registry/populator/Conversion662_649.java delete mode 100644 core/src/main/java/org/geysermc/geyser/registry/populator/Conversion671_662.java create mode 100644 core/src/main/java/org/geysermc/geyser/registry/populator/Conversion685_671.java delete mode 100644 core/src/main/resources/bedrock/block_palette.1_20_40.nbt delete mode 100644 core/src/main/resources/bedrock/block_palette.1_20_50.nbt delete mode 100644 core/src/main/resources/bedrock/block_palette.1_20_60.nbt delete mode 100644 core/src/main/resources/bedrock/block_palette.1_20_70.nbt create mode 100644 core/src/main/resources/bedrock/block_palette.1_21_0.nbt delete mode 100644 core/src/main/resources/bedrock/creative_items.1_20_40.json delete mode 100644 core/src/main/resources/bedrock/creative_items.1_20_50.json delete mode 100644 core/src/main/resources/bedrock/creative_items.1_20_60.json rename core/src/main/resources/bedrock/{creative_items.1_20_70.json => creative_items.1_21_0.json} (78%) delete mode 100644 core/src/main/resources/bedrock/runtime_item_states.1_20_40.json delete mode 100644 core/src/main/resources/bedrock/runtime_item_states.1_20_50.json delete mode 100644 core/src/main/resources/bedrock/runtime_item_states.1_20_60.json rename core/src/main/resources/bedrock/{runtime_item_states.1_20_70.json => runtime_item_states.1_21_0.json} (95%) diff --git a/README.md b/README.md index 9257af9ac..dd2d096ec 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/81 and Minecraft Java 1.20.5/1.20.6 +### Currently supporting Minecraft Bedrock 1.20.80 - 1.21.0 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/inventory/holder/BlockInventoryHolder.java b/core/src/main/java/org/geysermc/geyser/inventory/holder/BlockInventoryHolder.java index 9c8e5de15..cdda4fe4c 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 @@ -163,6 +163,7 @@ public class BlockInventoryHolder extends InventoryHolder { ContainerClosePacket packet = new ContainerClosePacket(); packet.setId((byte) inventory.getBedrockId()); packet.setServerInitiated(true); + packet.setType(ContainerType.CONTAINER); session.sendUpstreamPacket(packet); return; } 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 6bd767fb7..4c459573a 100644 --- a/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java +++ b/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java @@ -224,7 +224,7 @@ class CodecProcessor { @SuppressWarnings("unchecked") static BedrockCodec processCodec(BedrockCodec codec) { - return codec.toBuilder() + BedrockCodec.Builder codecBuilder = codec.toBuilder() // Illegal unused serverbound EDU packets .updateSerializer(PhotoTransferPacket.class, ILLEGAL_SERIALIZER) .updateSerializer(LabTablePacket.class, ILLEGAL_SERIALIZER) @@ -236,6 +236,7 @@ class CodecProcessor { .updateSerializer(PurchaseReceiptPacket.class, ILLEGAL_SERIALIZER) // Illegal unused serverbound packets that are deprecated .updateSerializer(ClientCheatAbilityPacket.class, ILLEGAL_SERIALIZER) + .updateSerializer(CraftingEventPacket.class, ILLEGAL_SERIALIZER) // Illegal unusued serverbound packets that relate to unused features .updateSerializer(PlayerAuthInputPacket.class, ILLEGAL_SERIALIZER) .updateSerializer(ClientCacheBlobStatusPacket.class, ILLEGAL_SERIALIZER) @@ -243,7 +244,6 @@ class CodecProcessor { .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) @@ -260,22 +260,25 @@ class CodecProcessor { .updateSerializer(PlayerHotbarPacket.class, PLAYER_HOTBAR_SERIALIZER) .updateSerializer(PlayerSkinPacket.class, PLAYER_SKIN_SERIALIZER) .updateSerializer(SetEntityDataPacket.class, SET_ENTITY_DATA_SERIALIZER) - .updateSerializer(SetEntityMotionPacket.class, codec.getProtocolVersion() < 662 ? - SET_ENTITY_MOTION_SERIALIZER_V291 : - SET_ENTITY_MOTION_SERIALIZER_V662) + .updateSerializer(SetEntityMotionPacket.class, 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) - // // Illegal bidirectional packets + // Illegal bidirectional packets .updateSerializer(DebugInfoPacket.class, ILLEGAL_SERIALIZER) .updateSerializer(EditorNetworkPacket.class, ILLEGAL_SERIALIZER) .updateSerializer(ScriptMessagePacket.class, ILLEGAL_SERIALIZER) - // // Ignored bidirectional packets + // Ignored bidirectional packets .updateSerializer(ClientCacheStatusPacket.class, IGNORED_SERIALIZER) .updateSerializer(SimpleEventPacket.class, IGNORED_SERIALIZER) - .updateSerializer(TickSyncPacket.class, IGNORED_SERIALIZER) - .updateSerializer(MultiplayerSettingsPacket.class, IGNORED_SERIALIZER) - .build(); + .updateSerializer(MultiplayerSettingsPacket.class, IGNORED_SERIALIZER); + + if (codec.getProtocolVersion() < 685) { + // Ignored bidirectional packets + codecBuilder.updateSerializer(TickSyncPacket.class, IGNORED_SERIALIZER); + } + + return codecBuilder.build(); } /** 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 f9292671f..1c58288c7 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -27,11 +27,8 @@ package org.geysermc.geyser.network; 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.codec.v662.Bedrock_v662; import org.cloudburstmc.protocol.bedrock.codec.v671.Bedrock_v671; +import org.cloudburstmc.protocol.bedrock.codec.v685.Bedrock_v685; import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodec; @@ -50,8 +47,8 @@ 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.toBuilder() - .minecraftVersion("1.20.81") + public static final BedrockCodec DEFAULT_BEDROCK_CODEC = CodecProcessor.processCodec(Bedrock_v685.CODEC.toBuilder() + .minecraftVersion("1.21.0") .build()); /** @@ -66,20 +63,11 @@ public final class GameProtocol { private static final PacketCodec DEFAULT_JAVA_CODEC = MinecraftCodec.CODEC; static { - SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v622.CODEC.toBuilder() - .minecraftVersion("1.20.40/1.20.41") - .build())); - SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v630.CODEC.toBuilder() - .minecraftVersion("1.20.50/1.20.51") - .build())); - SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v649.CODEC.toBuilder() - .minecraftVersion("1.20.60/1.20.62") - .build())); - SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v662.CODEC.toBuilder() - .minecraftVersion("1.20.70/1.20.73") + SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v671.CODEC.toBuilder() + .minecraftVersion("1.20.80/1.20.81") .build())); SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(DEFAULT_BEDROCK_CODEC.toBuilder() - .minecraftVersion("1.20.80/1.20.81") + .minecraftVersion("1.21.0") .build())); } @@ -99,16 +87,8 @@ 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(); - } - - 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(); + public static boolean isPre1_21_0(GeyserSession session) { + return session.getUpstream().getProtocolVersion() < Bedrock_v685.CODEC.getProtocolVersion(); } /** diff --git a/core/src/main/java/org/geysermc/geyser/network/InvalidPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/InvalidPacketHandler.java index 3e836711b..1b653891e 100644 --- a/core/src/main/java/org/geysermc/geyser/network/InvalidPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/InvalidPacketHandler.java @@ -47,7 +47,9 @@ public class InvalidPacketHandler extends ChannelInboundHandlerAdapter { if (!(rootCause instanceof IllegalArgumentException)) { - super.exceptionCaught(ctx, cause); + // Kick users that cause exceptions + session.getGeyser().getLogger().warning("Exception caught in session of" + session.bedrockUsername() + ": " + rootCause.getMessage()); + session.disconnect("An internal error occurred!"); return; } 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 6eadbd0e5..936935306 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 @@ -38,11 +38,8 @@ import it.unimi.dsi.fastutil.objects.*; import org.cloudburstmc.blockstateupdater.BlockStateUpdater; import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; import org.cloudburstmc.nbt.*; -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.codec.v685.Bedrock_v685; import org.cloudburstmc.protocol.bedrock.data.BlockPropertyData; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.geysermc.geyser.GeyserImpl; @@ -125,12 +122,8 @@ 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()), 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()), Conversion671_662::remapBlock) - .put(ObjectIntPair.of("1_20_80", Bedrock_v671.CODEC.getProtocolVersion()), tag -> tag) + .put(ObjectIntPair.of("1_20_80", Bedrock_v671.CODEC.getProtocolVersion()), Conversion685_671::remapBlock) + .put(ObjectIntPair.of("1_21_0", Bedrock_v685.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/Conversion630_622.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion630_622.java deleted file mode 100644 index 398eabc3c..000000000 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion630_622.java +++ /dev/null @@ -1,217 +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.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) - */ -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) { - mapping = Conversion649_630.remapItem(item, mapping); - - String replacement = ITEMS.get(mapping.getBedrockIdentifier()); - if (replacement == null) { - return mapping; - } else { - return mapping.withBedrockIdentifier(replacement); - } - } - - static NbtMap remapBlock(NbtMap tag) { - tag = Conversion649_630.remapBlock(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/Conversion649_630.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion649_630.java deleted file mode 100644 index 70a5e1ad9..000000000 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion649_630.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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; - -public class Conversion649_630 { - - static GeyserMappingItem remapItem(@SuppressWarnings("unused") Item item, GeyserMappingItem mapping) { - mapping = Conversion662_649.remapItem(item, mapping); - - String identifer = mapping.getBedrockIdentifier(); - - switch (identifer) { - 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; } - } - } - - 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; - } -} 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 deleted file mode 100644 index 041afdbc8..000000000 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion662_649.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * 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: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"); - 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) { - mapping = Conversion671_662.remapItem(item, mapping); - - String identifer = mapping.getBedrockIdentifier(); - - 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) { - 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_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); } - 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) { - tag = Conversion671_662.remapBlock(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 (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"; - - 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/Conversion671_662.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion671_662.java deleted file mode 100644 index 29ab3f2e5..000000000 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion671_662.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * 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 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_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(); - - if (!NEW_BLOCKS.contains(identifer)) { - 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); } - 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 (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", "");; - - 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/Conversion685_671.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion685_671.java new file mode 100644 index 000000000..250fd9d9f --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion685_671.java @@ -0,0 +1,205 @@ +/* + * 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 Conversion685_671 { + private static final List NEW_CORAL_BLOCKS = List.of("minecraft:tube_coral_block", "minecraft:brain_coral_block", "minecraft:bubble_coral_block", "minecraft:fire_coral_block", "minecraft:horn_coral_block", "minecraft:dead_tube_coral_block", "minecraft:dead_brain_coral_block", "minecraft:dead_bubble_coral_block", "minecraft:dead_fire_coral_block", "minecraft:dead_horn_coral_block"); + private static final List NEW_DOUBLE_PLANTS = List.of("minecraft:sunflower", "minecraft:lilac", "minecraft:tall_grass", "minecraft:large_fern", "minecraft:rose_bush", "minecraft:peony"); + private static final List NEW_STONE_BLOCK_SLABS = List.of("minecraft:smooth_stone_slab", "minecraft:sandstone_slab", "minecraft:petrified_oak_slab", "minecraft:cobblestone_slab", "minecraft:brick_slab", "minecraft:stone_brick_slab", "minecraft:quartz_slab", "minecraft:nether_brick_slab"); + private static final List NEW_TALLGRASSES = List.of("minecraft:fern", "minecraft:short_grass"); + private static final List OMINOUS_BLOCKS = List.of("minecraft:trial_spawner", "minecraft:vault"); + private static final List NEW_BLOCKS = Stream.of(NEW_CORAL_BLOCKS, NEW_DOUBLE_PLANTS, NEW_STONE_BLOCK_SLABS, NEW_TALLGRASSES).flatMap(List::stream).toList(); + private static final List MODIFIED_BLOCKS = Stream.of(NEW_BLOCKS, OMINOUS_BLOCKS).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_CORAL_BLOCKS.contains(identifer)) { + switch (identifer) { + case "minecraft:tube_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(0); } + case "minecraft:brain_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(1); } + case "minecraft:bubble_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(2); } + case "minecraft:fire_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(3); } + case "minecraft:horn_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(4); } + case "minecraft:dead_tube_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(8); } + case "minecraft:dead_brain_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(9); } + case "minecraft:dead_bubble_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(10); } + case "minecraft:dead_fire_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(11); } + case "minecraft:dead_horn_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(12); } + } + } + + if (NEW_DOUBLE_PLANTS.contains(identifer)) { + switch (identifer) { + case "minecraft:sunflower" -> { return mapping.withBedrockIdentifier("minecraft:double_plant").withBedrockData(0); } + case "minecraft:lilac" -> { return mapping.withBedrockIdentifier("minecraft:double_plant").withBedrockData(1); } + case "minecraft:tall_grass" -> { return mapping.withBedrockIdentifier("minecraft:double_plant").withBedrockData(2); } + case "minecraft:large_fern" -> { return mapping.withBedrockIdentifier("minecraft:double_plant").withBedrockData(3); } + case "minecraft:rose_bush" -> { return mapping.withBedrockIdentifier("minecraft:double_plant").withBedrockData(4); } + case "minecraft:peony" -> { return mapping.withBedrockIdentifier("minecraft:double_plant").withBedrockData(5); } + } + } + + if (NEW_STONE_BLOCK_SLABS.contains(identifer)) { + switch (identifer) { + case "minecraft:smooth_stone_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab").withBedrockData(0); } + case "minecraft:sandstone_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab").withBedrockData(1); } + case "minecraft:petrified_oak_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab").withBedrockData(2); } + case "minecraft:cobblestone_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab").withBedrockData(3); } + case "minecraft:brick_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab").withBedrockData(4); } + case "minecraft:stone_brick_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab").withBedrockData(5); } + case "minecraft:quartz_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab").withBedrockData(6); } + case "minecraft:nether_brick_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab").withBedrockData(7); } + } + } + + if (NEW_TALLGRASSES.contains(identifer)) { + switch (identifer) { + case "minecraft:short_grass" -> { return mapping.withBedrockIdentifier("minecraft:tallgrass").withBedrockData(1); } + case "minecraft:fern" -> { return mapping.withBedrockIdentifier("minecraft:tallgrass").withBedrockData(2); } + } + } + + return mapping; + } + + static NbtMap remapBlock(NbtMap tag) { + final String name = tag.getString("name"); + + if (!MODIFIED_BLOCKS.contains(name)) { + return tag; + } + + if (OMINOUS_BLOCKS.contains(name)) { + NbtMapBuilder builder = tag.getCompound("states").toBuilder(); + builder.remove("ominous"); + return tag.toBuilder().putCompound("states", builder.build()).build(); + } + + String replacement; + + if (NEW_CORAL_BLOCKS.contains(name)) { + replacement = "minecraft:coral_block"; + String coralColor; + boolean deadBit = name.startsWith("minecraft:dead_"); + + switch(name) { + case "minecraft:tube_coral_block", "minecraft:dead_tube_coral_block" -> coralColor = "blue"; + case "minecraft:brain_coral_block", "minecraft:dead_brain_coral_block" -> coralColor = "pink"; + case "minecraft:bubble_coral_block", "minecraft:dead_bubble_coral_block" -> coralColor = "purple"; + case "minecraft:fire_coral_block", "minecraft:dead_fire_coral_block" -> coralColor = "yellow"; + case "minecraft:horn_coral_block", "minecraft:dead_horn_coral_block" -> coralColor = "red"; + default -> throw new IllegalStateException("Unexpected value: " + name); + } + + NbtMap states = tag.getCompound("states") + .toBuilder() + .putString("coral_color", coralColor) + .putBoolean("dead_bit", deadBit) + .build(); + + return tag.toBuilder().putString("name", replacement).putCompound("states", states).build(); + } + + if (NEW_DOUBLE_PLANTS.contains(name)) { + replacement = "minecraft:double_plant"; + String doublePlantType; + + switch(name) { + case "minecraft:sunflower" -> doublePlantType = "sunflower"; + case "minecraft:lilac" -> doublePlantType = "syringa"; + case "minecraft:tall_grass" -> doublePlantType = "grass"; + case "minecraft:large_fern" -> doublePlantType = "fern"; + case "minecraft:rose_bush" -> doublePlantType = "rose"; + case "minecraft:peony" -> doublePlantType = "paeonia"; + default -> throw new IllegalStateException("Unexpected value: " + name); + } + + NbtMap states = tag.getCompound("states") + .toBuilder() + .putString("double_plant_type", doublePlantType) + .build(); + + return tag.toBuilder().putString("name", replacement).putCompound("states", states).build(); + } + + if (NEW_STONE_BLOCK_SLABS.contains(name)) { + replacement = "minecraft:stone_block_slab"; + String stoneSlabType; + + switch(name) { + case "minecraft:smooth_stone_slab" -> stoneSlabType = "smooth_stone"; + case "minecraft:sandstone_slab" -> stoneSlabType = "sandstone"; + case "minecraft:petrified_oak_slab" -> stoneSlabType = "wood"; + case "minecraft:cobblestone_slab" -> stoneSlabType = "cobblestone"; + case "minecraft:brick_slab" -> stoneSlabType = "brick"; + case "minecraft:stone_brick_slab" -> stoneSlabType = "stone_brick"; + case "minecraft:quartz_slab" -> stoneSlabType = "quartz"; + case "minecraft:nether_brick_slab" -> stoneSlabType = "nether_brick"; + default -> throw new IllegalStateException("Unexpected value: " + name); + } + + NbtMap states = tag.getCompound("states") + .toBuilder() + .putString("stone_slab_type", stoneSlabType) + .build(); + + return tag.toBuilder().putString("name", replacement).putCompound("states", states).build(); + } + + if (NEW_TALLGRASSES.contains(name)) { + replacement = "minecraft:tallgrass"; + String tallGrassType; + + switch(name) { + case "minecraft:short_grass" -> tallGrassType = "tall"; + case "minecraft:fern" -> tallGrassType = "fern"; + default -> throw new IllegalStateException("Unexpected value: " + name); + } + + NbtMap states = tag.getCompound("states") + .toBuilder() + .putString("tall_grass_type", tallGrassType) + .build(); + + return tag.toBuilder().putString("name", replacement).putCompound("states", states).build(); + } + + return tag; + } +} 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 b2d238ddb..a43df3f52 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 @@ -53,7 +53,6 @@ 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; @@ -325,13 +324,11 @@ 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); - - if (GameProtocol.is1_20_60orHigher(protocolVersion)) { - propertyTag.putCompound("vanilla_block_data", NbtMap.builder() + .putList("properties", NbtType.COMPOUND, properties) + .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 10d87a8a9..a6fa164c1 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,7 +44,6 @@ 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; @@ -260,18 +259,11 @@ public class CustomItemRegistryPopulator { } 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(); - } + NbtMap iconMap = NbtMap.builder() + .putCompound("textures", NbtMap.builder() + .putString("default", customItemData.icon()) + .build()) + .build(); itemProperties.putCompound("minecraft:icon", iconMap); if (customItemData.creativeCategory().isPresent()) { @@ -427,64 +419,56 @@ public class CustomItemRegistryPopulator { // 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()); + 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); + 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); - } + 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); } - } 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()); + 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); - // keep item enchantable; also works on 1.20.50 - itemProperties.putString("enchantable_slot", mapping.replace("minecraft:", "")); + 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); + } } } 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 d3a4bed84..5fcea504f 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,11 +38,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.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.codec.v685.Bedrock_v685; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; @@ -62,7 +59,6 @@ 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.*; @@ -91,11 +87,8 @@ 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(), 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(), Collections.emptyMap(), Conversion671_662::remapItem)); - paletteVersions.add(new PaletteVersion("1_20_80", Bedrock_v671.CODEC.getProtocolVersion())); + paletteVersions.add(new PaletteVersion("1_20_80", Bedrock_v671.CODEC.getProtocolVersion(), Collections.emptyMap(), Conversion685_671::remapItem)); + paletteVersions.add(new PaletteVersion("1_21_0", Bedrock_v685.CODEC.getProtocolVersion())); GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap(); @@ -602,18 +595,11 @@ public class ItemRegistryPopulator { NbtMapBuilder componentBuilder = NbtMap.builder(); // Conveniently, as of 1.16.200, the furnace minecart has a texture AND translation string already. // 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(); - } + NbtMap iconMap = NbtMap.builder() + .putCompound("textures", NbtMap.builder() + .putString("default", "minecart_furnace") + .build()) + .build(); itemProperties.putCompound("minecraft:icon", iconMap); componentBuilder.putCompound("minecraft:display_name", NbtMap.builder().putString("value", "item.minecartFurnace.name").build()); diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/RecipeRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/RecipeRegistryPopulator.java index 928ab8df9..4c6d53518 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 @@ -35,6 +35,7 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtUtils; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; +import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.RecipeUnlockingRequirement; import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.MultiRecipeData; import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.RecipeData; import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.ShapedRecipeData; @@ -173,7 +174,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, false); + inputs.stream().map(ItemDescriptorWithCount::fromItem).toList(), Collections.singletonList(output), uuid, "crafting_table", 0, netId, false, RecipeUnlockingRequirement.INVALID); } List inputs = new ObjectArrayList<>(); for (JsonNode entry : node.get("inputs")) { @@ -196,7 +197,7 @@ public class RecipeRegistryPopulator { inputs.stream().map(ItemDescriptorWithCount::fromItem).toList(), Collections.singletonList(output), uuid, "crafting_table", 0, netId); } return ShapelessRecipeData.shapeless(uuid.toString(), - 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, RecipeUnlockingRequirement.INVALID); } private static ItemData getBedrockItemFromIdentifierJson(ItemMapping mapping, JsonNode itemNode) { 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 69f61b181..9d2a3ef06 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -1546,6 +1546,10 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { startGamePacket.setRewindHistorySize(0); startGamePacket.setServerAuthoritativeBlockBreaking(false); + startGamePacket.setServerId(""); + startGamePacket.setWorldId(""); + startGamePacket.setScenarioId(""); + upstream.sendPacket(startGamePacket); } 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 c6c3c7dd6..8fe1e96c0 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 @@ -35,7 +35,6 @@ import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.*; import org.geysermc.geyser.inventory.updater.ContainerInventoryUpdater; import org.geysermc.geyser.level.block.Blocks; -import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.BlockEntityUtils; import org.geysermc.geyser.util.InventoryUtils; @@ -44,7 +43,6 @@ import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponen 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; @@ -152,13 +150,6 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator } else if (lecternContainer.getBlockEntityTag() == null) { 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 - // 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 (book.getComponents() != null) { int pages = 0; @@ -205,16 +196,6 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator lecternContainer.setPosition(position); BlockEntityUtils.updateBlockEntity(session, blockEntityTag, 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); - InventoryUtils.closeInventory(session, inventory.getJavaId(), false); - } } } 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 36752e582..18d6a22eb 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 @@ -550,6 +550,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { ContainerClosePacket packet = new ContainerClosePacket(); packet.setServerInitiated(true); packet.setId((byte) ContainerId.INVENTORY); + packet.setType(org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.INVENTORY); session.sendUpstreamPacket(packet); } 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 4bc727397..06531eff2 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 @@ -152,6 +152,7 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator { ContainerClosePacket packet = new ContainerClosePacket(); packet.setId((byte) inventory.getBedrockId()); packet.setServerInitiated(true); + packet.setType(ContainerType.MINECART_CHEST); session.sendUpstreamPacket(packet); return; } 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 1ea686536..959797d41 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 @@ -42,7 +42,6 @@ import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.level.block.type.BlockState; -import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; @@ -331,10 +330,6 @@ public class BedrockActionTranslator extends PacketTranslator1zWLFM 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

g-=;VUl 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⁡z#A(DebW+` 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%0D8NL_yw6CPSm^x#@W)*%Q+? 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 bpUvdU1E#~Pzl`yiv-g&@bjG3vY-s-jSX!9v 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 deleted file mode 100644 index 0eecda74f72dcf026d3f665c050d04a1f8485bb8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 170466 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 JkFhIPadz0t*h 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

oYIzSyh{iiN^y?}E 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 S3Ddm$_?t%ZPkIIGv;P4hJo(K4 diff --git a/core/src/main/resources/bedrock/block_palette.1_20_70.nbt b/core/src/main/resources/bedrock/block_palette.1_20_70.nbt deleted file mode 100644 index 8f4957b95013dd748bac4ed50c3e370729664453..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 176502 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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 diff --git a/core/src/main/resources/bedrock/block_palette.1_21_0.nbt b/core/src/main/resources/bedrock/block_palette.1_21_0.nbt new file mode 100644 index 0000000000000000000000000000000000000000..57366fc57f4456dd195497c435f5e5c7b397075d GIT binary patch literal 177397 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�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

<8kA1=h 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 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 deleted file mode 100644 index b2c0bfe04..000000000 --- a/core/src/main/resources/bedrock/creative_items.1_20_40.json +++ /dev/null @@ -1,5787 +0,0 @@ -{ - "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/creative_items.1_20_50.json b/core/src/main/resources/bedrock/creative_items.1_20_50.json deleted file mode 100644 index d93aa4c00..000000000 --- a/core/src/main/resources/bedrock/creative_items.1_20_50.json +++ /dev/null @@ -1,5995 +0,0 @@ -{ - "items": [ - { - "id": "minecraft:oak_planks", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19wbGFua3MECQBuYW1lX2hhc2ilMDLR92rQ4wMKAG5ldHdvcmtfaWS2GotyCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:spruce_planks", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9wbGFua3MECQBuYW1lX2hhc2iumBkmFGFE8gMKAG5ldHdvcmtfaWSo8TFgCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:birch_planks", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX3BsYW5rcwQJAG5hbWVfaGFzaLrrAKJqV2WFAwoAbmV0d29ya19pZL+e3ZAKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:jungle_planks", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9wbGFua3MECQBuYW1lX2hhc2iBM3k4T3FAugMKAG5ldHdvcmtfaWSXUmBCCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:acacia_planks", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9wbGFua3MECQBuYW1lX2hhc2g60edJxO5/aAMKAG5ldHdvcmtfaWTUXozECgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:dark_oak_planks", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX3BsYW5rcwQJAG5hbWVfaGFzaAr64wkQ9cA7AwoAbmV0d29ya19pZFbMeR0KBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:mangrove_planks", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX3BsYW5rcwQJAG5hbWVfaGFzaPvLtcEA0F8xAwoAbmV0d29ya19pZEvnlCYKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:cherry_planks", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9wbGFua3MECQBuYW1lX2hhc2hNIvVh/lVW7gMKAG5ldHdvcmtfaWQTXpRoCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:bamboo_planks", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19wbGFua3MECQBuYW1lX2hhc2gYnjNz7SCCjgMKAG5ldHdvcmtfaWTi8ySSCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:bamboo_mosaic", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19tb3NhaWMECQBuYW1lX2hhc2izSEgiMKOp/AMKAG5ldHdvcmtfaWQZ/p8xCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:crimson_planks", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fcGxhbmtzBAkAbmFtZV9oYXNoJc5IKqNXJnwDCgBuZXR3b3JrX2lkwtJDdQoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:warped_planks", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9wbGFua3MECQBuYW1lX2hhc2g3yGXEWhe6LgMKAG5ldHdvcmtfaWStTABvCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSE4JosCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCwBjb2JibGVzdG9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWTUvV6XCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEQBtb3NzeV9jb2JibGVzdG9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWT4opb2CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBwBncmFuaXRlCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQAMQTVCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBwBkaW9yaXRlCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQIbDOcCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCABhbmRlc2l0ZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSZKhusCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCQBzYW5kc3RvbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSp4zgCCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlDQByZWRfc2FuZHN0b25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRbqVHTCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCwBzdG9uZV9icmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRr0ZT/CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEQBtb3NzeV9zdG9uZV9icmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRnLis3CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBQBicmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQNLzfSCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlDABuZXRoZXJfYnJpY2sIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQ5h0xwCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEAByZWRfbmV0aGVyX2JyaWNrCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWS9J0B2CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCQBlbmRfYnJpY2sIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRPbkJeCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCgBwcmlzbWFyaW5lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:blackstone_wall", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsYWNrc3RvbmVfd2FsbAQJAG5hbWVfaGFzaMP8XppUSU1RAwoAbmV0d29ya19pZMbeBBsKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:polished_blackstone_wall", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfd2FsbAQJAG5hbWVfaGFzaP6SwV08YwzAAwoAbmV0d29ya19pZAJLsz8KBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:polished_blackstone_brick_wall", - "block_state_b64": "CgAACAQAbmFtZSgAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfd2FsbAQJAG5hbWVfaGFzaBBIDZbHxiEzAwoAbmV0d29ya19pZEbLV8cKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:cobbled_deepslate_wall", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3dhbGwECQBuYW1lX2hhc2iECY5oKxeT+gMKAG5ldHdvcmtfaWRCnPrFCgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:deepslate_tile_wall", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3dhbGwECQBuYW1lX2hhc2jz7N+PeuEXgQMKAG5ldHdvcmtfaWTqw4s4CgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:polished_deepslate_wall", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV93YWxsBAkAbmFtZV9oYXNoHxjTdj9pevMDCgBuZXR3b3JrX2lkIvBYYwoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:deepslate_brick_wall", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja193YWxsBAkAbmFtZV9oYXNoEs3EQrjroyEDCgBuZXR3b3JrX2lkwlrCGwoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:mud_brick_wall", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om11ZF9icmlja193YWxsBAkAbmFtZV9oYXNov9b98ATpUSwDCgBuZXR3b3JrX2lkH/1WZQoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:oak_fence", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0Om9ha19mZW5jZQQJAG5hbWVfaGFzaGEmid7AaCWRAwoAbmV0d29ya19pZDvPEXcKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:spruce_fence", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnNwcnVjZV9mZW5jZQQJAG5hbWVfaGFzaPQCm+aX1ZQeAwoAbmV0d29ya19pZD1QUEoKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:birch_fence", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJpcmNoX2ZlbmNlBAkAbmFtZV9oYXNo6CJ2ATpANfgDCgBuZXR3b3JrX2lkmCUV2QoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:jungle_fence", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0Omp1bmdsZV9mZW5jZQQJAG5hbWVfaGFzaOX4cD9uAmsdAwoAbmV0d29ya19pZHz1VxkKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:acacia_fence", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmFjYWNpYV9mZW5jZQQJAG5hbWVfaGFzaGjn+RlKVDH6AwoAbmV0d29ya19pZNVGubwKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:dark_oak_fence", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmRhcmtfb2FrX2ZlbmNlBAkAbmFtZV9oYXNoGPj0gCgM0c0DCgBuZXR3b3JrX2lk2w+gEwoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:mangrove_fence", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hbmdyb3ZlX2ZlbmNlBAkAbmFtZV9oYXNowwAd7tPu9bsDCgBuZXR3b3JrX2lkKEcd0goGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:cherry_fence", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNoZXJyeV9mZW5jZQQJAG5hbWVfaGFzaFmtUfHfTxcxAwoAbmV0d29ya19pZPCBxAIKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:bamboo_fence", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJhbWJvb19mZW5jZQQJAG5hbWVfaGFzaCKRbxfXsfkiAwoAbmV0d29ya19pZJNXKFcKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:nether_brick_fence", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0Om5ldGhlcl9icmlja19mZW5jZQQJAG5hbWVfaGFzaA6030ngawxcAwoAbmV0d29ya19pZLnjLF4KBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:crimson_fence", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNyaW1zb25fZmVuY2UECQBuYW1lX2hhc2jhUhKv1HGj9AMKAG5ldHdvcmtfaWR3OH3OCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:warped_fence", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OndhcnBlZF9mZW5jZQQJAG5hbWVfaGFzaJfb3/YuKmOWAwoAbmV0d29ya19pZCpaGC8KBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:fence_gate", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmZlbmNlX2dhdGUECQBuYW1lX2hhc2hTxpjEDmRzAwMKAG5ldHdvcmtfaWR+T9kTCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:spruce_fence_gate", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnNwcnVjZV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoanTVB84HRbkDCgBuZXR3b3JrX2lkEnw5egoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:birch_fence_gate", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmJpcmNoX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2jmfPklI8azSwMKAG5ldHdvcmtfaWQL77/BCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:jungle_fence_gate", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0Omp1bmdsZV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNobYVQkfBomIcDCgBuZXR3b3JrX2lkA1zgtgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:acacia_fence_gate", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmFjYWNpYV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoZnrLUx/XSekDCgBuZXR3b3JrX2lkHg/kTgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:dark_oak_fence_gate", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmRhcmtfb2FrX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2j2PTvdJJHcVQMKAG5ldHdvcmtfaWTwjOCeCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:mangrove_fence_gate", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om1hbmdyb3ZlX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2i/kOhBKiI/dAMKAG5ldHdvcmtfaWSfweCSCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:cherry_fence_gate", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmNoZXJyeV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoKWLgCk0z+PsDCgBuZXR3b3JrX2lk/9bTZQoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:bamboo_fence_gate", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmJhbWJvb19mZW5jZV9nYXRlBAkAbmFtZV9oYXNopH1JrUgwdIADCgBuZXR3b3JrX2lkzIpPywoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:crimson_fence_gate", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmNyaW1zb25fZmVuY2VfZ2F0ZQQJAG5hbWVfaGFzaHE3Gfd0Z2d2AwoAbmV0d29ya19pZDQzVbEKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQsAaW5fd2FsbF9iaXQAAQgAb3Blbl9iaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:warped_fence_gate", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OndhcnBlZF9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoy0oIBjDIG4kDCgBuZXR3b3JrX2lkkf+/3QoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:normal_stone_stairs", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om5vcm1hbF9zdG9uZV9zdGFpcnMECQBuYW1lX2hhc2hAEktZZOkGIwMKAG5ldHdvcmtfaWQeH1ALCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:stone_stairs", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX3N0YWlycwQJAG5hbWVfaGFzaNRjqVC5GRVDAwoAbmV0d29ya19pZDcCv+MKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:mossy_cobblestone_stairs", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lX3N0YWlycwQJAG5hbWVfaGFzaMVSTq5z9n1RAwoAbmV0d29ya19pZFIfrhkKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:oak_stairs", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19zdGFpcnMECQBuYW1lX2hhc2jk/HFzdXy0FQMKAG5ldHdvcmtfaWQJjyzBCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:spruce_stairs", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9zdGFpcnMECQBuYW1lX2hhc2iznygw7uBPBQMKAG5ldHdvcmtfaWTv+is3CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:birch_stairs", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX3N0YWlycwQJAG5hbWVfaGFzaPfhbL619a3GAwoAbmV0d29ya19pZFyPlHAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:jungle_stairs", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9zdGFpcnMECQBuYW1lX2hhc2jodJsHUbOVxQMKAG5ldHdvcmtfaWR0z5d4CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:acacia_stairs", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9zdGFpcnMECQBuYW1lX2hhc2h3x1NmD43IqQMKAG5ldHdvcmtfaWS7Jwz6CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:dark_oak_stairs", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX3N0YWlycwQJAG5hbWVfaGFzaMfwkbYPbNmAAwoAbmV0d29ya19pZCmBYKAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:mangrove_stairs", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX3N0YWlycwQJAG5hbWVfaGFzaNpUDY+uGMpyAwoAbmV0d29ya19pZChzUAsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:cherry_stairs", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9zdGFpcnMECQBuYW1lX2hhc2jMtr0v9JY4zwMKAG5ldHdvcmtfaWRQwq31CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:bamboo_stairs", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19zdGFpcnMECQBuYW1lX2hhc2jFOzWL8PalKwMKAG5ldHdvcmtfaWTVPh42CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:bamboo_mosaic_stairs", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJhbWJvb19tb3NhaWNfc3RhaXJzBAkAbmFtZV9oYXNoNLPiveSHPaoDCgBuZXR3b3JrX2lk44PHjgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:stone_brick_stairs", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0b25lX2JyaWNrX3N0YWlycwQJAG5hbWVfaGFzaN6tQViRo5cwAwoAbmV0d29ya19pZDMyMgIKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:mossy_stone_brick_stairs", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0Om1vc3N5X3N0b25lX2JyaWNrX3N0YWlycwQJAG5hbWVfaGFzaIB/Zv5YBPuYAwoAbmV0d29ya19pZANTOsMKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:sandstone_stairs", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnNhbmRzdG9uZV9zdGFpcnMECQBuYW1lX2hhc2hOyA0BoYUOPQMKAG5ldHdvcmtfaWSV/834CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:smooth_sandstone_stairs", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnNtb290aF9zYW5kc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNoB+CuCd8Ruz8DCgBuZXR3b3JrX2lksR+m8QoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:red_sandstone_stairs", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNoPs0LpHPL24YDCgBuZXR3b3JrX2lkLYVt3woGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:smooth_red_sandstone_stairs", - "block_state_b64": "CgAACAQAbmFtZSUAbWluZWNyYWZ0OnNtb290aF9yZWRfc2FuZHN0b25lX3N0YWlycwQJAG5hbWVfaGFzaBvjtQv5pf+MAwoAbmV0d29ya19pZMHNND8KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:granite_stairs", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmdyYW5pdGVfc3RhaXJzBAkAbmFtZV9oYXNoGzpvtoqKQjgDCgBuZXR3b3JrX2lkPkcB1goGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:polished_granite_stairs", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2dyYW5pdGVfc3RhaXJzBAkAbmFtZV9oYXNo3PvbSfEQklIDCgBuZXR3b3JrX2lkMmEm3AoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:diorite_stairs", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmRpb3JpdGVfc3RhaXJzBAkAbmFtZV9oYXNoi73T8VQuZmcDCgBuZXR3b3JrX2lk6i6nBQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:polished_diorite_stairs", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2Rpb3JpdGVfc3RhaXJzBAkAbmFtZV9oYXNoFKRJd5Wk5L0DCgBuZXR3b3JrX2lkbt2ioAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:andesite_stairs", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmFuZGVzaXRlX3N0YWlycwQJAG5hbWVfaGFzaO5w2FKBw76EAwoAbmV0d29ya19pZKhXEgUKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:polished_andesite_stairs", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2FuZGVzaXRlX3N0YWlycwQJAG5hbWVfaGFzaNcZZ/zmLInIAwoAbmV0d29ya19pZJTHrlEKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:brick_stairs", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJyaWNrX3N0YWlycwQJAG5hbWVfaGFzaMyt+cRDk5O2AwoAbmV0d29ya19pZNeMh58KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:nether_brick_stairs", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om5ldGhlcl9icmlja19zdGFpcnMECQBuYW1lX2hhc2jRqIoOXgifBAMKAG5ldHdvcmtfaWQDiw5yCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:red_nether_brick_stairs", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNogQvosSbcj7kDCgBuZXR3b3JrX2lkx2IMtAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:end_brick_stairs", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmVuZF9icmlja19zdGFpcnMECQBuYW1lX2hhc2hmlAk+QhsUsQMKAG5ldHdvcmtfaWTN7KFaCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:quartz_stairs", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9zdGFpcnMECQBuYW1lX2hhc2hmvpvOqGi6egMKAG5ldHdvcmtfaWRmUTh7CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:smooth_quartz_stairs", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnNtb290aF9xdWFydHpfc3RhaXJzBAkAbmFtZV9oYXNoNZZ9rX0qZOsDCgBuZXR3b3JrX2lkzsgQyQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:purpur_stairs", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnB1cl9zdGFpcnMECQBuYW1lX2hhc2ifwDxeezXD7gMKAG5ldHdvcmtfaWTT+rxiCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:prismarine_stairs", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnByaXNtYXJpbmVfc3RhaXJzBAkAbmFtZV9oYXNooTHSZ+IrYtcDCgBuZXR3b3JrX2lkxTJfeAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:dark_prismarine_stairs", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmRhcmtfcHJpc21hcmluZV9zdGFpcnMECQBuYW1lX2hhc2hIciLmam4o4AMKAG5ldHdvcmtfaWTVu7TCCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:prismarine_bricks_stairs", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnByaXNtYXJpbmVfYnJpY2tzX3N0YWlycwQJAG5hbWVfaGFzaNIjq1oBlZMMAwoAbmV0d29ya19pZGEFwLYKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:crimson_stairs", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fc3RhaXJzBAkAbmFtZV9oYXNoZJqIzCBpCq4DCgBuZXR3b3JrX2lktXE00AoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:warped_stairs", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9zdGFpcnMECQBuYW1lX2hhc2hOkY27jLD4RQMKAG5ldHdvcmtfaWQ+E5VrCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:blackstone_stairs", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmJsYWNrc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNokdoUb76p9McDCgBuZXR3b3JrX2lk5fWI5goGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:polished_blackstone_stairs", - "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNolCFtFIE8MmADCgBuZXR3b3JrX2lkGTf7sgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:polished_blackstone_brick_stairs", - "block_state_b64": "CgAACAQAbmFtZSoAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNonks6UlfpOmkDCgBuZXR3b3JrX2lkgYeOdAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:cut_copper_stairs", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmN1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoHfoAXYq5G3MDCgBuZXR3b3JrX2lkeetf7woGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:exposed_cut_copper_stairs", - "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcl9zdGFpcnMECQBuYW1lX2hhc2howneQGtZ9cgMKAG5ldHdvcmtfaWSg73zdCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:weathered_cut_copper_stairs", - "block_state_b64": "CgAACAQAbmFtZSUAbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyX3N0YWlycwQJAG5hbWVfaGFzaP+R5loXxrVgAwoAbmV0d29ya19pZOnbRf4KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:oxidized_cut_copper_stairs", - "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNo6Jeoq5rsPxsDCgBuZXR3b3JrX2lkmRjDnQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:waxed_cut_copper_stairs", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoh07CQj0/SR8DCgBuZXR3b3JrX2lkmYqoqAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:waxed_exposed_cut_copper_stairs", - "block_state_b64": "CgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcl9zdGFpcnMECQBuYW1lX2hhc2guVct1ilmxTwMKAG5ldHdvcmtfaWQgCPROCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:waxed_weathered_cut_copper_stairs", - "block_state_b64": "CgAACAQAbmFtZSsAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyX3N0YWlycwQJAG5hbWVfaGFzaPXC8Sz/phCpAwoAbmV0d29ya19pZHlwHVsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:waxed_oxidized_cut_copper_stairs", - "block_state_b64": "CgAACAQAbmFtZSoAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoaqGdkuhxVZUDCgBuZXR3b3JrX2lkYQXzzgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:cobbled_deepslate_stairs", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3N0YWlycwQJAG5hbWVfaGFzaPIfa+TpyJcIAwoAbmV0d29ya19pZJUvOYIKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:deepslate_tile_stairs", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3N0YWlycwQJAG5hbWVfaGFzaGFRFzB72mN2AwoAbmV0d29ya19pZJEOgIsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:polished_deepslate_stairs", - "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV9zdGFpcnMECQBuYW1lX2hhc2iNCYxVik9sGAMKAG5ldHdvcmtfaWSRVPnYCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:deepslate_brick_stairs", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja19zdGFpcnMECQBuYW1lX2hhc2hIasOahEf83wMKAG5ldHdvcmtfaWQ1qEDCCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:mud_brick_stairs", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0Om11ZF9icmlja19zdGFpcnMECQBuYW1lX2hhc2gt3qxK1NWajAMKAG5ldHdvcmtfaWSm9N3MCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "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": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OnRyYXBkb29yBAkAbmFtZV9oYXNotYiAJGtN0xADCgBuZXR3b3JrX2lkyTAWkAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:spruce_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnNwcnVjZV90cmFwZG9vcgQJAG5hbWVfaGFzaOwlfbgBkUW4AwoAbmV0d29ya19pZPHy1K0KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:birch_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmJpcmNoX3RyYXBkb29yBAkAbmFtZV9oYXNoSLtLweOLJ7wDCgBuZXR3b3JrX2lkeJWDfgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:jungle_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Omp1bmdsZV90cmFwZG9vcgQJAG5hbWVfaGFzaDP/TnM9wyCIAwoAbmV0d29ya19pZEy2fJoKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:acacia_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmFjYWNpYV90cmFwZG9vcgQJAG5hbWVfaGFzaMj8xi3vmEKOAwoAbmV0d29ya19pZOHj8E8KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:dark_oak_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmRhcmtfb2FrX3RyYXBkb29yBAkAbmFtZV9oYXNomB2GGJQ2aOMDCgBuZXR3b3JrX2lko5ZHTwoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:mangrove_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0Om1hbmdyb3ZlX3RyYXBkb29yBAkAbmFtZV9oYXNooV3kQsQUUmkDCgBuZXR3b3JrX2lkkF/mxAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:cherry_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNoZXJyeV90cmFwZG9vcgQJAG5hbWVfaGFzaH/PefpfdHgtAwoAbmV0d29ya19pZOA7eNgKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:bamboo_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmJhbWJvb190cmFwZG9vcgQJAG5hbWVfaGFzaJrEOpsTwtKCAwoAbmV0d29ya19pZLvbPz8KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:iron_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Omlyb25fdHJhcGRvb3IECQBuYW1lX2hhc2gwA+IumsEiGQMKAG5ldHdvcmtfaWTvSVl/CgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:crimson_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmNyaW1zb25fdHJhcGRvb3IECQBuYW1lX2hhc2jHXufTnwUkYgMKAG5ldHdvcmtfaWQLjMYVCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:warped_trapdoor", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OndhcnBlZF90cmFwZG9vcgQJAG5hbWVfaGFzaA20wG/+vkd6AwoAbmV0d29ya19pZHKR/hYKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:iron_bars", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0Omlyb25fYmFycwQJAG5hbWVfaGFzaPuefWSNAe56AwoAbmV0d29ya19pZN2LB5IKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:glass", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmdsYXNzBAkAbmFtZV9oYXNowGJByfWff6gDCgBuZXR3b3JrX2lk0hdLNwoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:white_stained_glass", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OndoaXRlX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2iHubqoMbu9fAMKAG5ldHdvcmtfaWRndBrUCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:light_gray_stained_glass", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaKKa+LrRsHQhAwoAbmV0d29ya19pZEv2giYKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:gray_stained_glass", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmdyYXlfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaIETy7Y/HZREAwoAbmV0d29ya19pZDomVrUKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:black_stained_glass", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmJsYWNrX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2iV6BCwpfDMmwMKAG5ldHdvcmtfaWSV7doJCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:brown_stained_glass", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmJyb3duX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2igsEiq5np8JgMKAG5ldHdvcmtfaWRMzE/lCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:red_stained_glass", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnJlZF9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNoCa2J12/lQoIDCgBuZXR3b3JrX2lk283lWAoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:orange_stained_glass", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0Om9yYW5nZV9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNozgjAuvzhxGsDCgBuZXR3b3JrX2lkW5CkhQoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:yellow_stained_glass", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnllbGxvd19zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNo7EbHMd5WVugDCgBuZXR3b3JrX2lkkdDyXQoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:lime_stained_glass", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmxpbWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaBtZA1nZtwcFAwoAbmV0d29ya19pZDxX85UKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:green_stained_glass", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmdyZWVuX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2h91ptDgbehWwMKAG5ldHdvcmtfaWTlDhnECgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:cyan_stained_glass", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmN5YW5fc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaBkIYQ8nQLqbAwoAbmV0d29ya19pZOL1lHsKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:light_blue_stained_glass", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaLt05n1G0fiSAwoAbmV0d29ya19pZNbwulIKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:blue_stained_glass", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmJsdWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaPhLocSfzduRAwoAbmV0d29ya19pZENsjFwKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:purple_stained_glass", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnB1cnBsZV9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNoJk0DhRO0szUDCgBuZXR3b3JrX2lkD98ZxgoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:magenta_stained_glass", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0Om1hZ2VudGFfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaFEDeFiJj3zSAwoAbmV0d29ya19pZG+iFRoKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:pink_stained_glass", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnBpbmtfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaDijTX87ywxhAwoAbmV0d29ya19pZKdEricKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:tinted_glass", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnRpbnRlZF9nbGFzcwQJAG5hbWVfaGFzaAFZWSamk6KdAwoAbmV0d29ya19pZGSvWX8KBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:glass_pane", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmdsYXNzX3BhbmUECQBuYW1lX2hhc2gRSBHwNMQ4gQMKAG5ldHdvcmtfaWRGwixuCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:white_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OndoaXRlX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaHgxQmgJVtRrAwoAbmV0d29ya19pZBEr/DYKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:light_gray_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNon0aQw9lNkSEDCgBuZXR3b3JrX2lk9dp5VgoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:gray_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmdyYXlfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNors74IIw+2MMDCgBuZXR3b3JrX2lkmrGO5woGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:black_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmJsYWNrX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaOK/5ZRRd+M1AwoAbmV0d29ya19pZDv++oQKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:brown_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmJyb3duX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLHeGJyRFTIWAwoAbmV0d29ya19pZMz9L0wKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:red_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnJlZF9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2gGr4x6JheAywMKAG5ldHdvcmtfaWQBjCTmCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:orange_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0Om9yYW5nZV9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2hbHxPD2gEbEAMKAG5ldHdvcmtfaWSt/7a5CgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:yellow_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OnllbGxvd19zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2g9tl4aOCyZBwMKAG5ldHdvcmtfaWTXRAS7CgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:lime_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmxpbWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNo3CtUyLwoGegDCgBuZXR3b3JrX2lkYJDnggoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:green_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmdyZWVuX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaJo6YP7IMy9SAwoAbmV0d29ya19pZHOnixoKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:cyan_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmN5YW5fc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoti97c6QrbLQDCgBuZXR3b3JrX2lkUqFUeQoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:light_blue_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNovDg/gQle104DCgBuZXR3b3JrX2lkFuy4MQoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:blue_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmJsdWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoGc57tiexbQMDCgBuZXR3b3JrX2lk1eBLUAoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:purple_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OnB1cnBsZV9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2hDJHYdd0FdfQMKAG5ldHdvcmtfaWSNsdK5CgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:magenta_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0Om1hZ2VudGFfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNo3pcOw5bs5XoDCgBuZXR3b3JrX2lkVbOR7AoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:pink_stained_glass_pane", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnBpbmtfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoWRhSACMWgswDCgBuZXR3b3JrX2lkIR92xwoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:ladder", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmxhZGRlcgQJAG5hbWVfaGFzaKBhqheJVOz+AwoAbmV0d29ya19pZCgvzlsKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:scaffolding", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnNjYWZmb2xkaW5nBAkAbmFtZV9oYXNoYrkevrqcljwDCgBuZXR3b3JrX2lkD13mlAoGAHN0YXRlcwMJAHN0YWJpbGl0eQAAAAABDwBzdGFiaWxpdHlfY2hlY2sAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWTkNl0JCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQwAc21vb3RoX3N0b25lAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:stone_block_slab4", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkQJoxlgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNAUAc3RvbmUAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWRHh04KCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQsAY29iYmxlc3RvbmUAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkVRZB+woGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhEAbW9zc3lfY29iYmxlc3RvbmUAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:wooden_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkBaobgAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUDAG9hawADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:wooden_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkhz9TeQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUGAHNwcnVjZQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:wooden_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lk3HkwowoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUFAGJpcmNoAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:wooden_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkDIBqVQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUGAGp1bmdsZQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:wooden_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkL5hFYAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUGAGFjYWNpYQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:wooden_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Ondvb2Rlbl9zbGFiBAkAbmFtZV9oYXNoBVBkRBCCh4MDCgBuZXR3b3JrX2lkKRUHSQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20ICQB3b29kX3R5cGUIAGRhcmtfb2FrAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:mangrove_slab", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Om1hbmdyb3ZlX3NsYWIECQBuYW1lX2hhc2jYCcmhJPeNMwMKAG5ldHdvcmtfaWQx6U1yCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:cherry_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNoZXJyeV9zbGFiBAkAbmFtZV9oYXNoTt0MmVn/mqoDCgBuZXR3b3JrX2lk2VVsZQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:bamboo_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJhbWJvb19zbGFiBAkAbmFtZV9oYXNoo1xuFqINeLYDCgBuZXR3b3JrX2lkVC+0twoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:bamboo_mosaic_slab", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmJhbWJvb19tb3NhaWNfc2xhYgQJAG5hbWVfaGFzaNbVRBZ/ChI3AwoAbmV0d29ya19pZOLZHFMKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWQSiInOCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQsAc3RvbmVfYnJpY2sAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:stone_block_slab4", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkoF89tgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNBEAbW9zc3lfc3RvbmVfYnJpY2sAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWSkoAE4CgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQkAc2FuZHN0b25lAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:stone_block_slab4", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkWfF7pgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNA0AY3V0X3NhbmRzdG9uZQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkbKRChAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAc21vb3RoX3NhbmRzdG9uZQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkBlrvqAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMg0AcmVkX3NhbmRzdG9uZQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:stone_block_slab4", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkRWFXuwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNBEAY3V0X3JlZF9zYW5kc3RvbmUAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkom8neQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxQAc21vb3RoX3JlZF9zYW5kc3RvbmUAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkd1ZaWgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwcAZ3Jhbml0ZQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkISH4iwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxAAcG9saXNoZWRfZ3Jhbml0ZQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkqxEDMwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwcAZGlvcml0ZQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkSYs86QoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxAAcG9saXNoZWRfZGlvcml0ZQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkq6BU6goGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwgAYW5kZXNpdGUAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkTSXY8AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxEAcG9saXNoZWRfYW5kZXNpdGUAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWQiYHKTCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQUAYnJpY2sAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWTk/0LfCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQwAbmV0aGVyX2JyaWNrAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk/hXQ7AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcmVkX25ldGhlcl9icmljawADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkYJNxrwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMw8AZW5kX3N0b25lX2JyaWNrAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWRlj0/sCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQYAcXVhcnR6AAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:stone_block_slab4", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkMae+2goGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNA0Ac21vb3RoX3F1YXJ0egADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk+kMHGAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMgYAcHVycHVyAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkKOSOMAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcHJpc21hcmluZV9yb3VnaAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk8igLCQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMg8AcHJpc21hcmluZV9kYXJrAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkSFbyEwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcHJpc21hcmluZV9icmljawADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:crimson_slab", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNyaW1zb25fc2xhYgQJAG5hbWVfaGFzaKZ+EfP0ZYOZAwoAbmV0d29ya19pZAxRUWAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:warped_slab", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OndhcnBlZF9zbGFiBAkAbmFtZV9oYXNo/AT0e/Z9W7UDCgBuZXR3b3JrX2lk1yq11AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:blackstone_slab", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsYWNrc3RvbmVfc2xhYgQJAG5hbWVfaGFzaF/DD4ZUlNgtAwoAbmV0d29ya19pZGy1DjwKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:polished_blackstone_slab", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfc2xhYgQJAG5hbWVfaGFzaDYnuUs86EWfAwoAbmV0d29ya19pZJj2bXIKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:polished_blackstone_brick_slab", - "block_state_b64": "CgAACAQAbmFtZSgAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfc2xhYgQJAG5hbWVfaGFzaKySLqvHc4xXAwoAbmV0d29ya19pZOyWX94KBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:cut_copper_slab", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmN1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaDsNpb2qs4iBAwoAbmV0d29ya19pZOTm2nsKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:exposed_cut_copper_slab", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcl9zbGFiBAkAbmFtZV9oYXNoahQ5OwIQb7kDCgBuZXR3b3JrX2lkrUlZLwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:weathered_cut_copper_slab", - "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyX3NsYWIECQBuYW1lX2hhc2hBIuGIOVVXogMKAG5ldHdvcmtfaWQgnaDiCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:oxidized_cut_copper_slab", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaOptj9ycfpaDAwoAbmV0d29ya19pZMzFSRgKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:waxed_cut_copper_slab", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaAlx6DZOCTHzAwoAbmV0d29ya19pZFRBvDAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:waxed_exposed_cut_copper_slab", - "block_state_b64": "CgAACAQAbmFtZScAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcl9zbGFiBAkAbmFtZV9oYXNo3KqS5OnhtRIDCgBuZXR3b3JrX2lkHTGcTgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:waxed_weathered_cut_copper_slab", - "block_state_b64": "CgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyX3NsYWIECQBuYW1lX2hhc2gzZ1oX0HCFtwMKAG5ldHdvcmtfaWSgJR+XCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:waxed_oxidized_cut_copper_slab", - "block_state_b64": "CgAACAQAbmFtZSgAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaMjjTnLu1KcqAwoAbmV0d29ya19pZIxsnFYKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:cobbled_deepslate_slab", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3NsYWIECQBuYW1lX2hhc2gwJIVWK1TM2QMKAG5ldHdvcmtfaWTYAoX5CgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:polished_deepslate_slab", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV9zbGFiBAkAbmFtZV9oYXNoC/Adiz8k6RYDCgBuZXR3b3JrX2lkuFYMAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:deepslate_tile_slab", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3NsYWIECQBuYW1lX2hhc2hPydV6emzIXAMKAG5ldHdvcmtfaWQwlbFCCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:deepslate_brick_slab", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja19zbGFiBAkAbmFtZV9oYXNoSv62V7iw10UDCgBuZXR3b3JrX2lkWMoragoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:mud_brick_slab", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om11ZF9icmlja19zbGFiBAkAbmFtZV9oYXNoq/tGBQWkv08DCgBuZXR3b3JrX2lkl4nnMwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:brick_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJyaWNrX2Jsb2NrBAkAbmFtZV9oYXNo5Qc2E005S3oDCgBuZXR3b3JrX2lkqeGWRgoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:chiseled_nether_bricks", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmNoaXNlbGVkX25ldGhlcl9icmlja3MECQBuYW1lX2hhc2g31SBPTcUK1QMKAG5ldHdvcmtfaWS8TJ+TCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:cracked_nether_bricks", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmNyYWNrZWRfbmV0aGVyX2JyaWNrcwQJAG5hbWVfaGFzaAdC6eKzXT5tAwoAbmV0d29ya19pZIUSejwKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:quartz_bricks", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9icmlja3MECQBuYW1lX2hhc2jSZO590dd8sAMKAG5ldHdvcmtfaWSc5xCLCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:stonebrick", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWQ5kni1CgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQcAZGVmYXVsdAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:stonebrick", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWTDw813CgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQUAbW9zc3kAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:stonebrick", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWSTvQGECgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQcAY3JhY2tlZAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:stonebrick", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWQIM0OwCgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQgAY2hpc2VsZWQAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:end_bricks", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmVuZF9icmlja3MECQBuYW1lX2hhc2hIUFfxNLZaFgMKAG5ldHdvcmtfaWQ/vDihCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:prismarine", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWSH021WCgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBgBicmlja3MAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:polished_blackstone_bricks", - "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tzBAkAbmFtZV9oYXNoIHgsgIdzKXcDCgBuZXR3b3JrX2lkUw9b3woGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:cracked_polished_blackstone_bricks", - "block_state_b64": "CgAACAQAbmFtZSwAbWluZWNyYWZ0OmNyYWNrZWRfcG9saXNoZWRfYmxhY2tzdG9uZV9icmlja3MECQBuYW1lX2hhc2jQIO1GQDk80AMKAG5ldHdvcmtfaWQ3UlRYCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:gilded_blackstone", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmdpbGRlZF9ibGFja3N0b25lBAkAbmFtZV9oYXNoNoWt1ocG0HEDCgBuZXR3b3JrX2lktL8gUwoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:chiseled_polished_blackstone", - "block_state_b64": "CgAACAQAbmFtZSYAbWluZWNyYWZ0OmNoaXNlbGVkX3BvbGlzaGVkX2JsYWNrc3RvbmUECQBuYW1lX2hhc2gzFa+kEjCJgAMKAG5ldHdvcmtfaWR2NJX2CgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:deepslate_tiles", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlcwQJAG5hbWVfaGFzaGcLLx3NXAFvAwoAbmV0d29ya19pZI/G/xYKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:cracked_deepslate_tiles", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmNyYWNrZWRfZGVlcHNsYXRlX3RpbGVzBAkAbmFtZV9oYXNo9zWgkFuMM1QDCgBuZXR3b3JrX2lkGwY6OgoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:deepslate_bricks", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja3MECQBuYW1lX2hhc2gucvFmPdZxigMKAG5ldHdvcmtfaWSH4HDPCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:cracked_deepslate_bricks", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OmNyYWNrZWRfZGVlcHNsYXRlX2JyaWNrcwQJAG5hbWVfaGFzaN40aqhh9WqHAwoAbmV0d29ya19pZO9GPBQKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:chiseled_deepslate", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaEU7/uRG8HSBAwoAbmV0d29ya19pZEqmI0EKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:cobblestone", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvYmJsZXN0b25lBAkAbmFtZV9oYXNoPoK7mGlSUz4DCgBuZXR3b3JrX2lkLm7RZwoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:mossy_cobblestone", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lBAkAbmFtZV9oYXNoGJ67FCbkChMDCgBuZXR3b3JrX2lk/pYs1AoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:cobbled_deepslate", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlBAkAbmFtZV9oYXNoLUz9Y/ywmLwDCgBuZXR3b3JrX2lkNwzZ+AoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:smooth_stone", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnNtb290aF9zdG9uZQQJAG5hbWVfaGFzaMwf87/JaTNvAwoAbmV0d29ya19pZLkZICEKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:sandstone", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZB2wApMKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUHAGRlZmF1bHQAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:sandstone", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZB7E+eQKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGULAGhlaXJvZ2x5cGhzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:sandstone", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZFQnDaEKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUDAGN1dAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:sandstone", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZPO4A3IKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUGAHNtb290aAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:red_sandstone", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWRhNYiFCgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:red_sandstone", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTqXJr1CgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlCwBoZWlyb2dseXBocwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:red_sandstone", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTQRGkFCgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlAwBjdXQAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:red_sandstone", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTvAHWDCgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlBgBzbW9vdGgAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:coal_block", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmNvYWxfYmxvY2sECQBuYW1lX2hhc2jH8QQP3t5PiAMKAG5ldHdvcmtfaWRo+sR+CgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:dried_kelp_block", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmRyaWVkX2tlbHBfYmxvY2sECQBuYW1lX2hhc2iRoucexkrl8wMKAG5ldHdvcmtfaWQQCCrvCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:gold_block", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmdvbGRfYmxvY2sECQBuYW1lX2hhc2iYLshvjtXzFwMKAG5ldHdvcmtfaWTDJGBcCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:iron_block", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Omlyb25fYmxvY2sECQBuYW1lX2hhc2jYINmJQbvV/gMKAG5ldHdvcmtfaWRf7AbICgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "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==" - }, - { - "id": "minecraft:exposed_cut_copper", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcgQJAG5hbWVfaGFzaA85G3yv/w6pAwoAbmV0d29ya19pZMQhr0QKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:weathered_cut_copper", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyBAkAbmFtZV9oYXNoVgRV0fBaz88DCgBuZXR3b3JrX2lk/0cYugoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:oxidized_cut_copper", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2iP8WmFWOkriwMKAG5ldHdvcmtfaWQPdce7CgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:waxed_cut_copper", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2jumiwOZIqv2AMKAG5ldHdvcmtfaWQvuxx9CgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:waxed_exposed_cut_copper", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcgQJAG5hbWVfaGFzaPE/OfK6IoVMAwoAbmV0d29ya19pZHy5HkcKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:waxed_weathered_cut_copper", - "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyBAkAbmFtZV9oYXNoCA1xDp11bnwDCgBuZXR3b3JrX2lkDyEDVQoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "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==" - }, - { - "id": "minecraft:diamond_block", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmRpYW1vbmRfYmxvY2sECQBuYW1lX2hhc2iGKrxuvkytFQMKAG5ldHdvcmtfaWQQeQZXCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:lapis_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmxhcGlzX2Jsb2NrBAkAbmFtZV9oYXNoDZ44xdb2zVoDCgBuZXR3b3JrX2lktVy0BAoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:raw_iron_block", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJhd19pcm9uX2Jsb2NrBAkAbmFtZV9oYXNo9XyzNIQXxvwDCgBuZXR3b3JrX2lknms1QAoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:raw_copper_block", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnJhd19jb3BwZXJfYmxvY2sECQBuYW1lX2hhc2hw1KG0TNUGgwMKAG5ldHdvcmtfaWS1vGo/CgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:raw_gold_block", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJhd19nb2xkX2Jsb2NrBAkAbmFtZV9oYXNo6YuwuLwfOBwDCgBuZXR3b3JrX2lkLiQ5gQoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:quartz_block", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZEupC1AKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQcAZGVmYXVsdAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:quartz_block", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZM97+l0KBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQUAbGluZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:quartz_block", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZCbTfssKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQgAY2hpc2VsZWQICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:quartz_block", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZJss8V0KBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQYAc21vb3RoCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:prismarine", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWRFIsoGCgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:prismarine", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWTDNWOvCgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBABkYXJrAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:slime", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnNsaW1lBAkAbmFtZV9oYXNoHJiEEJx+JlkDCgBuZXR3b3JrX2lkfgfVzAoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:honey_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmhvbmV5X2Jsb2NrBAkAbmFtZV9oYXNo9zLYSUlelywDCgBuZXR3b3JrX2lko+dyWgoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:honeycomb_block", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmhvbmV5Y29tYl9ibG9jawQJAG5hbWVfaGFzaASIPuOCYd1oAwoAbmV0d29ya19pZKys4n4KBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:hay_block", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmhheV9ibG9jawQJAG5hbWVfaGFzaIB2VxKxX8EpAwoAbmV0d29ya19pZKuQSloKBgBzdGF0ZXMDCgBkZXByZWNhdGVkAAAAAAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:bone_block", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmJvbmVfYmxvY2sECQBuYW1lX2hhc2i4ZX576W9AWgMKAG5ldHdvcmtfaWTWGacQCgYAc3RhdGVzAwoAZGVwcmVjYXRlZAAAAAAICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:nether_brick", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0Om5ldGhlcl9icmljawQJAG5hbWVfaGFzaMxcRiheU+nXAwoAbmV0d29ya19pZMkmzloKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:red_nether_brick", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2sECQBuYW1lX2hhc2j8pRO4LfoECAMKAG5ldHdvcmtfaWRpdF0YCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:netherite_block", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om5ldGhlcml0ZV9ibG9jawQJAG5hbWVfaGFzaMghh6Zib/ZKAwoAbmV0d29ya19pZIz0mq0KBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:lodestone", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmxvZGVzdG9uZQQJAG5hbWVfaGFzaJ2gmHOTlXv8AwoAbmV0d29ya19pZEfgB4wKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:white_wool", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OndoaXRlX3dvb2wECQBuYW1lX2hhc2jRWB7vaIEDiQMKAG5ldHdvcmtfaWSO8paQCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:light_gray_wool", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfd29vbAQJAG5hbWVfaGFzaOpdQ1a2v4b3AwoAbmV0d29ya19pZIqZCYEKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:gray_wool", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmdyYXlfd29vbAQJAG5hbWVfaGFzaLsc1Lp1xdIOAwoAbmV0d29ya19pZFUs+HgKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:black_wool", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmJsYWNrX3dvb2wECQBuYW1lX2hhc2hP2HC6o0X4HAMKAG5ldHdvcmtfaWRUbORcCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:brown_wool", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmJyb3duX3dvb2wECQBuYW1lX2hhc2ig5IW89PrREwMKAG5ldHdvcmtfaWRjT9j8CgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:red_wool", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OnJlZF93b29sBAkAbmFtZV9oYXNoY4TBDq+mFgUDCgBuZXR3b3JrX2lktn9lcAoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:orange_wool", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om9yYW5nZV93b29sBAkAbmFtZV9oYXNoFstfrTZfSCgDCgBuZXR3b3JrX2lk+rqywwoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:yellow_wool", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnllbGxvd193b29sBAkAbmFtZV9oYXNoTFyus2RHegcDCgBuZXR3b3JrX2lkkKBhXAoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:lime_wool", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmxpbWVfd29vbAQJAG5hbWVfaGFzaNVnnzKiMxmeAwoAbmV0d29ya19pZG9b32kKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:green_wool", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmdyZWVuX3dvb2wECQBuYW1lX2hhc2i3mElRYHIcSQMKAG5ldHdvcmtfaWSssprwCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:cyan_wool", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmN5YW5fd29vbAQJAG5hbWVfaGFzaBNDfvHn8dqFAwoAbmV0d29ya19pZK0hAbgKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:light_blue_wool", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfd29vbAQJAG5hbWVfaGFzaLWFAUfyxFPNAwoAbmV0d29ya19pZL2oEugKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:blue_wool", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmJsdWVfd29vbAQJAG5hbWVfaGFzaLjHyxxbTWCLAwoAbmV0d29ya19pZPaLdFQKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:purple_wool", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnB1cnBsZV93b29sBAkAbmFtZV9oYXNojvFtqzjAf/4DCgBuZXR3b3JrX2lklqASNQoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:magenta_wool", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0Om1hZ2VudGFfd29vbAQJAG5hbWVfaGFzaGuOHvf+Pd4yAwoAbmV0d29ya19pZI4UoDQKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:pink_wool", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnBpbmtfd29vbAQJAG5hbWVfaGFzaPiVA2pFeoFLAwoAbmV0d29ya19pZOZRO6oKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:white_carpet", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OndoaXRlX2NhcnBldAQJAG5hbWVfaGFzaNeMHTI1fWPXAwoAbmV0d29ya19pZEahDFcKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:light_gray_carpet", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY2FycGV0BAkAbmFtZV9oYXNoHPw6ArBAsP0DCgBuZXR3b3JrX2lkQoAeUAoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:gray_carpet", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXlfY2FycGV0BAkAbmFtZV9oYXNoZVR0OI+1VRADCgBuZXR3b3JrX2lkETF4WwoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:black_carpet", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJsYWNrX2NhcnBldAQJAG5hbWVfaGFzaOk7LP9NptyhAwoAbmV0d29ya19pZFjmXtIKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:brown_carpet", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJyb3duX2NhcnBldAQJAG5hbWVfaGFzaNaXFyOsAvIvAwoAbmV0d29ya19pZHPjFuoKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:red_carpet", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9jYXJwZXQECQBuYW1lX2hhc2i9eSKBf6SO3wMKAG5ldHdvcmtfaWQuhI/KCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:orange_carpet", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Om9yYW5nZV9jYXJwZXQECQBuYW1lX2hhc2hIUkO4HlAdygMKAG5ldHdvcmtfaWSyKV9OCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:yellow_carpet", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19jYXJwZXQECQBuYW1lX2hhc2hSDKX3scCamwMKAG5ldHdvcmtfaWT8nq+ECgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:lime_carpet", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmxpbWVfY2FycGV0BAkAbmFtZV9oYXNo+6KFOpzsib4DCgBuZXR3b3JrX2lkT+DS4woGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:green_carpet", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmdyZWVuX2NhcnBldAQJAG5hbWVfaGFzaCHPMP9ltqFJAwoAbmV0d29ya19pZBgwAvAKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:cyan_carpet", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmN5YW5fY2FycGV0BAkAbmFtZV9oYXNobXf62dQBJj8DCgBuZXR3b3JrX2lkKVppLgoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:light_blue_carpet", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY2FycGV0BAkAbmFtZV9oYXNo20l4oktdZ3sDCgBuZXR3b3JrX2lkjdeMiwoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:blue_carpet", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfY2FycGV0BAkAbmFtZV9oYXNo3p3lsW0eQwsDCgBuZXR3b3JrX2lkAovdPQoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:purple_carpet", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnBsZV9jYXJwZXQECQBuYW1lX2hhc2jwIA9pW/qp7QMKAG5ldHdvcmtfaWTqJqhjCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:magenta_carpet", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hZ2VudGFfY2FycGV0BAkAbmFtZV9oYXNoFXT36YNNZhMDCgBuZXR3b3JrX2lk+tqsGAoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:pink_carpet", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfY2FycGV0BAkAbmFtZV9oYXNoHll72oqk+OoDCgBuZXR3b3JrX2lkrnBYDwoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:white_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OndoaXRlX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaFUk9iXVjwV8AwoAbmV0d29ya19pZJPZY8AKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:light_gray_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNo7EUk30hmUtYDCgBuZXR3b3JrX2lkh8jVIwoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:gray_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmdyYXlfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoW77af6WihdwDCgBuZXR3b3JrX2lkSsqC1woGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:black_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmJsYWNrX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaAfWYp0xtgcfAwoAbmV0d29ya19pZMWTC8EKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:brown_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmJyb3duX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaB74EeiLO46XAwoAbmV0d29ya19pZEDHKqwKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:red_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnJlZF9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2gjFut6Z/VH1gMKAG5ldHdvcmtfaWSvcmwYCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:orange_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0Om9yYW5nZV9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2gADDj2IJiw+gMKAG5ldHdvcmtfaWTHph0FCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:yellow_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnllbGxvd19jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2iy6qKNn3ob5wMKAG5ldHdvcmtfaWQZAI39CgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:lime_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmxpbWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNo4dYIPslbXPUDCgBuZXR3b3JrX2lk2O8X0AoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:green_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmdyZWVuX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaM/c9x2aJh3HAwoAbmV0d29ya19pZA0VfBMKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:cyan_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmN5YW5fY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNok+xKAe7XXjoDCgBuZXR3b3JrX2lkmkn6uwoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:light_blue_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNogScpIQceyAEDCgBuZXR3b3JrX2lkOmVSbgoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:blue_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJsdWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoFp7mmeL86r0DCgBuZXR3b3JrX2lkS3b3RQoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:purple_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnB1cnBsZV9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2iYcVU04hoStwMKAG5ldHdvcmtfaWQXimEjCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:magenta_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0Om1hZ2VudGFfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoy/70q6VPsWgDCgBuZXR3b3JrX2lkf9mxQwoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:pink_concrete_powder", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnBpbmtfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoVikSAf8DwV0DCgBuZXR3b3JrX2lku2MivwoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:white_concrete", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OndoaXRlX2NvbmNyZXRlBAkAbmFtZV9oYXNo6zAp7lsLlvkDCgBuZXR3b3JrX2lk3MAYQAoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:light_gray_concrete", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY29uY3JldGUECQBuYW1lX2hhc2hEtet5wuDIKAMKAG5ldHdvcmtfaWQISs02CgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:gray_concrete", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmdyYXlfY29uY3JldGUECQBuYW1lX2hhc2j92INnb0a83AMKAG5ldHdvcmtfaWQj8RHwCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:black_concrete", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmJsYWNrX2NvbmNyZXRlBAkAbmFtZV9oYXNo2X7NDIQmZ70DCgBuZXR3b3JrX2lk2uiVDQoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:brown_concrete", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmJyb3duX2NvbmNyZXRlBAkAbmFtZV9oYXNoeka02BwXf6oDCgBuZXR3b3JrX2lkYf+xDQoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:red_concrete", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZF9jb25jcmV0ZQQJAG5hbWVfaGFzaPWmNowLGubqAwoAbmV0d29ya19pZKwyx58KBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:orange_concrete", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om9yYW5nZV9jb25jcmV0ZQQJAG5hbWVfaGFzaAgE8XmaAi6+AwoAbmV0d29ya19pZMDQNz8KBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:yellow_concrete", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnllbGxvd19jb25jcmV0ZQQJAG5hbWVfaGFzaE6ONfJPBd0+AwoAbmV0d29ya19pZMarutwKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:lime_concrete", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmxpbWVfY29uY3JldGUECQBuYW1lX2hhc2gnd8JW6wmJcAMKAG5ldHdvcmtfaWTd47aoCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:green_concrete", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmdyZWVuX2NvbmNyZXRlBAkAbmFtZV9oYXNokbFxRKchQZkDCgBuZXR3b3JrX2lkmhZWUgoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:cyan_concrete", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmN5YW5fY29uY3JldGUECQBuYW1lX2hhc2hFRrWJ33qj1wMKAG5ldHdvcmtfaWQbi5b8CgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:light_blue_concrete", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY29uY3JldGUECQBuYW1lX2hhc2gHAe0kl0SE4AMKAG5ldHdvcmtfaWRL/GbSCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:blue_concrete", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJsdWVfY29uY3JldGUECQBuYW1lX2hhc2hiay301nnj1wMKAG5ldHdvcmtfaWRMvFXNCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:purple_concrete", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnB1cnBsZV9jb25jcmV0ZQQJAG5hbWVfaGFzaHBHflsPIwdXAwoAbmV0d29ya19pZCyKA5gKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:magenta_concrete", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0Om1hZ2VudGFfY29uY3JldGUECQBuYW1lX2hhc2gN7LuB/OvdZAMKAG5ldHdvcmtfaWTc6ZOdCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:pink_concrete", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnBpbmtfY29uY3JldGUECQBuYW1lX2hhc2ii2G5F0u3SOAMKAG5ldHdvcmtfaWSszGgrCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:clay", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OmNsYXkECQBuYW1lX2hhc2j/S6sKXRcpzwMKAG5ldHdvcmtfaWRmsb8nCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:hardened_clay", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmhhcmRlbmVkX2NsYXkECQBuYW1lX2hhc2jrnRwCJ0krJAMKAG5ldHdvcmtfaWRBCOrrCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:white_terracotta", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OndoaXRlX3RlcnJhY290dGEECQBuYW1lX2hhc2j3RSdgmnAIewMKAG5ldHdvcmtfaWSimKw+CgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:light_gray_terracotta", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmxpZ2h0X2dyYXlfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAz1Ri3wIxomAwoAbmV0d29ya19pZH5qgOcKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:gray_terracotta", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmdyYXlfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAXdSLAaNZ9vAwoAbmV0d29ya19pZM1QDV0KBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:black_terracotta", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmJsYWNrX3RlcnJhY290dGEECQBuYW1lX2hhc2jxssdv5vlbpgMKAG5ldHdvcmtfaWRE3Ru/CgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:brown_terracotta", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmJyb3duX3RlcnJhY290dGEECQBuYW1lX2hhc2gG4kPenmOF9gMKAG5ldHdvcmtfaWQ/i0iNCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:red_terracotta", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNo7fX56HXFejEDCgBuZXR3b3JrX2lk8tTF8QoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:orange_terracotta", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0Om9yYW5nZV90ZXJyYWNvdHRhBAkAbmFtZV9oYXNo0Hjmql3sruMDCgBuZXR3b3JrX2lklmqmkAoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:yellow_terracotta", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnllbGxvd190ZXJyYWNvdHRhBAkAbmFtZV9oYXNoqkyKKrmA3VcDCgBuZXR3b3JrX2lkaM/orAoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:lime_terracotta", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmxpbWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaANjADFOF9v7AwoAbmV0d29ya19pZJt0XsgKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:green_terracotta", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmdyZWVuX3RlcnJhY290dGEECQBuYW1lX2hhc2j5Ybq36yYwRQMKAG5ldHdvcmtfaWQ8kGdHCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:cyan_terracotta", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmN5YW5fdGVycmFjb3R0YQQJAG5hbWVfaGFzaN09COzMuHwAAwoAbmV0d29ya19pZIWPCzoKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:light_blue_terracotta", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmxpZ2h0X2JsdWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaOMytez7cOZiAwoAbmV0d29ya19pZFHK1UsKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:blue_terracotta", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsdWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaF6inyTK5RpAAwoAbmV0d29ya19pZF5mVZIKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:purple_terracotta", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnB1cnBsZV90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoKF7YG61yTbEDCgBuZXR3b3JrX2lkhtRDlwoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:magenta_terracotta", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0Om1hZ2VudGFfdGVycmFjb3R0YQQJAG5hbWVfaGFzaLWvtpAVtztyAwoAbmV0d29ya19pZN5SoakKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:pink_terracotta", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnBpbmtfdGVycmFjb3R0YQQJAG5hbWVfaGFzaJ7mzvyzSQZTAwoAbmV0d29ya19pZDJWe4YKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:white_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OndoaXRlX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoiVzCdoHAJo0DCgBuZXR3b3JrX2lkIlj9AAoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:silver_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnNpbHZlcl9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAVsA0CnhzA4AwoAbmV0d29ya19pZPnxtJEKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:gray_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmdyYXlfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2jvLZt9u/lF/AMKAG5ldHdvcmtfaWQVU8eFCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:black_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmJsYWNrX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoe8I4xAXbO5UDCgBuZXR3b3JrX2lk2Icb9AoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:brown_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmJyb3duX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoSiNZOobbpjoDCgBuZXR3b3JrX2lkJy0jwgoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:red_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnJlZF9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaBdWFGLmCLFVAwoAbmV0d29ya19pZMYBJSEKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:orange_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0Om9yYW5nZV9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaMyJMrnPr7szAwoAbmV0d29ya19pZN6+7TUKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:yellow_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnllbGxvd19nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaN6NaIhf6m0uAwoAbmV0d29ya19pZKRHXeoKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:lime_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmxpbWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2iF3E68/rB2EAMKAG5ldHdvcmtfaWSP7qQWCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:green_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmdyZWVuX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNow5mo8aQDFboDCgBuZXR3b3JrX2lkoF11kgoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:cyan_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmN5YW5fZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2gnNB+cCFRJhwMKAG5ldHdvcmtfaWT9buMtCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:light_blue_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSYAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2gladnCDBKCigMKAG5ldHdvcmtfaWS5CszFCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:blue_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmJsdWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2giOZK+2nB1igMKAG5ldHdvcmtfaWR+e22CCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:purple_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSIAbWluZWNyYWZ0OnB1cnBsZV9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaIQU03txeAfHAwoAbmV0d29ya19pZLKbSE4KBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:magenta_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSMAbWluZWNyYWZ0Om1hZ2VudGFfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2i/SNqDJbfjMgMKAG5ldHdvcmtfaWQKf9UvCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:pink_glazed_terracotta", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnBpbmtfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2hik8DVt4g+twMKAG5ldHdvcmtfaWTKzav2CgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:purpur_block", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnB1cnB1cl9ibG9jawQJAG5hbWVfaGFzaAgLwnUZGlzsAwoAbmV0d29ya19pZLD8ox4KBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQcAZGVmYXVsdAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:purpur_block", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnB1cnB1cl9ibG9jawQJAG5hbWVfaGFzaAgLwnUZGlzsAwoAbmV0d29ya19pZPSAFFsKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQUAbGluZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:packed_mud", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnBhY2tlZF9tdWQECQBuYW1lX2hhc2gHOMa121h4FgMKAG5ldHdvcmtfaWTUb6LyCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:mud_bricks", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Om11ZF9icmlja3MECQBuYW1lX2hhc2iDL/SVl/PewQMKAG5ldHdvcmtfaWSkBjaDCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:nether_wart_block", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0Om5ldGhlcl93YXJ0X2Jsb2NrBAkAbmFtZV9oYXNo9XGS4GNnlV4DCgBuZXR3b3JrX2lkh3apIgoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:warped_wart_block", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OndhcnBlZF93YXJ0X2Jsb2NrBAkAbmFtZV9oYXNo9IqDS9yUPJoDCgBuZXR3b3JrX2lkMpKAbAoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:shroomlight", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnNocm9vbWxpZ2h0BAkAbmFtZV9oYXNoZHCHcHX/HYADCgBuZXR3b3JrX2lkLG2JiwoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:crimson_nylium", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fbnlsaXVtBAkAbmFtZV9oYXNoOr6DJYW2bFYDCgBuZXR3b3JrX2lkuWpRDgoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:warped_nylium", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9ueWxpdW0ECQBuYW1lX2hhc2g0Zf89cfr3rwMKAG5ldHdvcmtfaWSu/kekCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:netherrack", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Om5ldGhlcnJhY2sECQBuYW1lX2hhc2i/r5ZyRsvPyQMKAG5ldHdvcmtfaWTAiTOACgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:basalt", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmJhc2FsdAQJAG5hbWVfaGFzaH+UQO2yWodiAwoAbmV0d29ya19pZBPNSV4KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:polished_basalt", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnBvbGlzaGVkX2Jhc2FsdAQJAG5hbWVfaGFzaMS+L0gMnRcBAwoAbmV0d29ya19pZF+/mHwKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:smooth_basalt", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnNtb290aF9iYXNhbHQECQBuYW1lX2hhc2jKPUdz89kuNAMKAG5ldHdvcmtfaWTkb/oVCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:soul_soil", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNvdWxfc29pbAQJAG5hbWVfaGFzaC1/87ccutuTAwoAbmV0d29ya19pZKc63SMKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:dirt", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OmRpcnQECQBuYW1lX2hhc2hXp6jnXAe+kQMKAG5ldHdvcmtfaWQmkQtoCgYAc3RhdGVzCAkAZGlydF90eXBlBgBub3JtYWwAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:dirt", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OmRpcnQECQBuYW1lX2hhc2hXp6jnXAe+kQMKAG5ldHdvcmtfaWQId9pLCgYAc3RhdGVzCAkAZGlydF90eXBlBgBjb2Fyc2UAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:farmland", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmZhcm1sYW5kBAkAbmFtZV9oYXNoxyQ5ag7LolADCgBuZXR3b3JrX2lkX618FQoGAHN0YXRlcwMSAG1vaXN0dXJpemVkX2Ftb3VudAAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:grass", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmdyYXNzBAkAbmFtZV9oYXNosppASPWFlsUDCgBuZXR3b3JrX2lkhLLQkQoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:grass_path", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmdyYXNzX3BhdGgECQBuYW1lX2hhc2i0/KZV8Qsy+gMKAG5ldHdvcmtfaWT7CcdzCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:podzol", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBvZHpvbAQJAG5hbWVfaGFzaBzqokRjH4Z1AwoAbmV0d29ya19pZPPS/GUKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:mycelium", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0Om15Y2VsaXVtBAkAbmFtZV9oYXNojTN09cKickIDCgBuZXR3b3JrX2lkLNPxXQoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:mud", - "block_state_b64": "CgAACAQAbmFtZQ0AbWluZWNyYWZ0Om11ZAQJAG5hbWVfaGFzaPb/3P+uLy+9AwoAbmV0d29ya19pZPIUlUkKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:stone", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lkIQ4xgAoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:iron_ore", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0Omlyb25fb3JlBAkAbmFtZV9oYXNoS7BYtLnfx3gDCgBuZXR3b3JrX2lk3loneQoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:gold_ore", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmdvbGRfb3JlBAkAbmFtZV9oYXNoC5Y+DUGXLC4DCgBuZXR3b3JrX2lkNhvMfwoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:diamond_ore", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmRpYW1vbmRfb3JlBAkAbmFtZV9oYXNokUOJ2wZZrGQDCgBuZXR3b3JrX2lk/dChVAoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:lapis_ore", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmxhcGlzX29yZQQJAG5hbWVfaGFzaMrmrUrSzb7qAwoAbmV0d29ya19pZMg+qK4KBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:redstone_ore", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZHN0b25lX29yZQQJAG5hbWVfaGFzaFHVnp8Wc4JbAwoAbmV0d29ya19pZKDYvQoKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:coal_ore", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmNvYWxfb3JlBAkAbmFtZV9oYXNo1OjA+Iuy51oDCgBuZXR3b3JrX2lk+R/aKAoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:copper_ore", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmNvcHBlcl9vcmUECQBuYW1lX2hhc2iSZduSntOzOwMKAG5ldHdvcmtfaWQtIuCnCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:emerald_ore", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmVtZXJhbGRfb3JlBAkAbmFtZV9oYXNoJTovr+VgINsDCgBuZXR3b3JrX2lknbkqCgoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:quartz_ore", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnF1YXJ0el9vcmUECQBuYW1lX2hhc2g0yNHLMK9TaQMKAG5ldHdvcmtfaWSzN7nzCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:nether_gold_ore", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om5ldGhlcl9nb2xkX29yZQQJAG5hbWVfaGFzaEJZ7segIBgBAwoAbmV0d29ya19pZNI9pDgKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:ancient_debris", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmFuY2llbnRfZGVicmlzBAkAbmFtZV9oYXNoNrbxMc9AwKcDCgBuZXR3b3JrX2lkrSNjEAoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:deepslate_iron_ore", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9pcm9uX29yZQQJAG5hbWVfaGFzaB/fDL9pgvXXAwoAbmV0d29ya19pZFA0bz4KBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:deepslate_gold_ore", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9nb2xkX29yZQQJAG5hbWVfaGFzaF9G7WYhKFinAwoAbmV0d29ya19pZHQTfBUKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:deepslate_diamond_ore", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV9kaWFtb25kX29yZQQJAG5hbWVfaGFzaEUH5USh+iD3AwoAbmV0d29ya19pZHP6VzAKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:deepslate_lapis_ore", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV9sYXBpc19vcmUECQBuYW1lX2hhc2j+yFxU/KZs1gMKAG5ldHdvcmtfaWRKINzICgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:deepslate_redstone_ore", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmRlZXBzbGF0ZV9yZWRzdG9uZV9vcmUECQBuYW1lX2hhc2iVgM3wWWD6ugMKAG5ldHdvcmtfaWReBdYRCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:deepslate_emerald_ore", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV9lbWVyYWxkX29yZQQJAG5hbWVfaGFzaNlfo5HTwS6wAwoAbmV0d29ya19pZNeie6sKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:deepslate_coal_ore", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9jb2FsX29yZQQJAG5hbWVfaGFzaIjikmcbRrPPAwoAbmV0d29ya19pZD9TiygKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:deepslate_copper_ore", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9jb3BwZXJfb3JlBAkAbmFtZV9oYXNottjV4Ev5LAQDCgBuZXR3b3JrX2lkP23rgQoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:gravel", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmdyYXZlbAQJAG5hbWVfaGFzaOFxz8XJd2r/AwoAbmV0d29ya19pZBpfI1sKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:granite", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmdyYW5pdGUECQBuYW1lX2hhc2iq+Dur2pw4AwMKAG5ldHdvcmtfaWT2NMfJCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:diorite", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmRpb3JpdGUECQBuYW1lX2hhc2iaFsq2iinZBQMKAG5ldHdvcmtfaWQqGE6XCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:andesite", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmFuZGVzaXRlBAkAbmFtZV9oYXNosaLIEnQQoSYDCgBuZXR3b3JrX2lkEApRZAoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:blackstone", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmJsYWNrc3RvbmUECQBuYW1lX2hhc2iMFYziD80D6QMKAG5ldHdvcmtfaWSrUryHCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:deepslate", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmRlZXBzbGF0ZQQJAG5hbWVfaGFzaKX5pAblxz8TAwoAbmV0d29ya19pZOJoQjsKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:polished_granite", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnBvbGlzaGVkX2dyYW5pdGUECQBuYW1lX2hhc2iLiEfys8pFIAMKAG5ldHdvcmtfaWTCxxcHCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:polished_diorite", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnBvbGlzaGVkX2Rpb3JpdGUECQBuYW1lX2hhc2hTxY4fKmNmlAMKAG5ldHdvcmtfaWTmtjdRCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:polished_andesite", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnBvbGlzaGVkX2FuZGVzaXRlBAkAbmFtZV9oYXNovl28uFk4HuQDCgBuZXR3b3JrX2lklFjuCwoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:polished_blackstone", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmUECQBuYW1lX2hhc2jT9fHCl6vWQQMKAG5ldHdvcmtfaWR/Ho6oCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:polished_deepslate", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaHC1edoaWF3uAwoAbmV0d29ya19pZCPeQsEKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:sand", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnNhbmQECQBuYW1lX2hhc2i6lthXXbAyWAMKAG5ldHdvcmtfaWTekU/mCgYAc3RhdGVzCAkAc2FuZF90eXBlBgBub3JtYWwAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:sand", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnNhbmQECQBuYW1lX2hhc2i6lthXXbAyWAMKAG5ldHdvcmtfaWSTgcqmCgYAc3RhdGVzCAkAc2FuZF90eXBlAwByZWQAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:cactus", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmNhY3R1cwQJAG5hbWVfaGFzaCG9zL0N4wvGAwoAbmV0d29ya19pZDeCERAKBgBzdGF0ZXMDAwBhZ2UAAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:oak_log", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0Om9ha19sb2cECQBuYW1lX2hhc2ho6TS+K7PZFQMKAG5ldHdvcmtfaWQjfjoxCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:stripped_oak_log", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnN0cmlwcGVkX29ha19sb2cECQBuYW1lX2hhc2h8dqh+OOHU4wMKAG5ldHdvcmtfaWSYKjdrCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:spruce_log", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnNwcnVjZV9sb2cECQBuYW1lX2hhc2hZ03qaLoF3WgMKAG5ldHdvcmtfaWRlFD8eCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:stripped_spruce_log", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX3NwcnVjZV9sb2cECQBuYW1lX2hhc2iNrhKjS5IyrgMKAG5ldHdvcmtfaWRQcEC3CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:birch_log", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmJpcmNoX2xvZwQJAG5hbWVfaGFzaBUzT3NxsZAnAwoAbmV0d29ya19pZBKN3VQKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:stripped_birch_log", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnN0cmlwcGVkX2JpcmNoX2xvZwQJAG5hbWVfaGFzaCFKS4AeuSidAwoAbmV0d29ya19pZN0IONIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:jungle_log", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Omp1bmdsZV9sb2cECQBuYW1lX2hhc2gkwW0KNulqDgMKAG5ldHdvcmtfaWQaziU/CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:stripped_jungle_log", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2p1bmdsZV9sb2cECQBuYW1lX2hhc2hAwMsgOk02JAMKAG5ldHdvcmtfaWQvls0eCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:acacia_log", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmFjYWNpYV9sb2cECQBuYW1lX2hhc2iV48VpYhjoYQMKAG5ldHdvcmtfaWRxEqe0CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:stripped_acacia_log", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2FjYWNpYV9sb2cECQBuYW1lX2hhc2hJb0lQqnEqlgMKAG5ldHdvcmtfaWRg3IdRCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:dark_oak_log", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRhcmtfb2FrX2xvZwQJAG5hbWVfaGFzaIWfVRd0XUo3AwoAbmV0d29ya19pZPMM7LYKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:stripped_dark_oak_log", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2Rhcmtfb2FrX2xvZwQJAG5hbWVfaGFzaPFTdxRdPwkOAwoAbmV0d29ya19pZDIzenIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:mangrove_log", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0Om1hbmdyb3ZlX2xvZwQJAG5hbWVfaGFzaHZe6DzPZBobAwoAbmV0d29ya19pZG6DuYkKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:stripped_mangrove_log", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX21hbmdyb3ZlX2xvZwQJAG5hbWVfaGFzaLqIBo4hwA//AwoAbmV0d29ya19pZPtRn7UKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:cherry_log", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmNoZXJyeV9sb2cECQBuYW1lX2hhc2hwFlaioppB1wMKAG5ldHdvcmtfaWS2sdXECgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:stripped_cherry_log", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2NoZXJyeV9sb2cECQBuYW1lX2hhc2i85H6G+WhXaAMKAG5ldHdvcmtfaWRjzoglCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:crimson_stem", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNyaW1zb25fc3RlbQQJAG5hbWVfaGFzaM0FzfL0UTKZAwoAbmV0d29ya19pZKvzID0KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:stripped_crimson_stem", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2NyaW1zb25fc3RlbQQJAG5hbWVfaGFzaDlA6nood57EAwoAbmV0d29ya19pZHrIqjIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:warped_stem", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OndhcnBlZF9zdGVtBAkAbmFtZV9oYXNon7cKfPZxdrUDCgBuZXR3b3JrX2lkerWyMwoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:stripped_warped_stem", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX3dhcnBlZF9zdGVtBAkAbmFtZV9oYXNoEw+y0dDPSd8DCgBuZXR3b3JrX2lkIQ9vBAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWSYGFlqCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlAwBvYWsAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWSxnUzvCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlAwBvYWsAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWToyw4RCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlBgBzcHJ1Y2UAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWTL0a3ZCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlBgBzcHJ1Y2UAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQV99vJCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlBQBiaXJjaAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQYDJk1CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlBQBiaXJjaAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWSfH48gCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlBgBqdW5nbGUAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQ44auiCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlBgBqdW5nbGUAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWSogpPYCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlBgBhY2FjaWEAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWSD7hT1CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlBgBhY2FjaWEAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQagb3gCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQACAkAd29vZF90eXBlCABkYXJrX29hawADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:wood", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Ondvb2QECQBuYW1lX2hhc2gbHdJFXQ1vNwMKAG5ldHdvcmtfaWQdnWU+CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQBCAkAd29vZF90eXBlCABkYXJrX29hawADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:mangrove_wood", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Om1hbmdyb3ZlX3dvb2QECQBuYW1lX2hhc2iXVxG0JG2fVAMKAG5ldHdvcmtfaWTok1JCCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:stripped_mangrove_wood", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX21hbmdyb3ZlX3dvb2QECQBuYW1lX2hhc2h7CkbaBF7/WAMKAG5ldHdvcmtfaWQLAX88CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:cherry_wood", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNoZXJyeV93b29kBAkAbmFtZV9oYXNoAW8srlmpBM8DCgBuZXR3b3JrX2lkEALMfAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AQwAc3RyaXBwZWRfYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:stripped_cherry_wood", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX2NoZXJyeV93b29kBAkAbmFtZV9oYXNo/e7KXv+CB38DCgBuZXR3b3JrX2lkg5aVtQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:crimson_hyphae", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25faHlwaGFlBAkAbmFtZV9oYXNouRmKmfSqEWADCgBuZXR3b3JrX2lk+Tm5rQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:stripped_crimson_hyphae", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OnN0cmlwcGVkX2NyaW1zb25faHlwaGFlBAkAbmFtZV9oYXNoFffwmABq4LUDCgBuZXR3b3JrX2lkZAlUbgoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:warped_hyphae", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9oeXBoYWUECQBuYW1lX2hhc2hn8plQUr6pmQMKAG5ldHdvcmtfaWRU2AIBCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:stripped_warped_hyphae", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX3dhcnBlZF9oeXBoYWUECQBuYW1lX2hhc2irKq+HYPSgjQMKAG5ldHdvcmtfaWSbrOPDCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:bamboo_block", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJhbWJvb19ibG9jawQJAG5hbWVfaGFzaAbDeur6stIBAwoAbmV0d29ya19pZCJAwn0KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:stripped_bamboo_block", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2JhbWJvb19ibG9jawQJAG5hbWVfaGFzaJpwytpZOZM9AwoAbmV0d29ya19pZKuRbNEKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:leaves", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmxlYXZlcwQJAG5hbWVfaGFzaACPIsusW0mnAwoAbmV0d29ya19pZOmqtzMKBgBzdGF0ZXMIDQBvbGRfbGVhZl90eXBlAwBvYWsBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:leaves", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmxlYXZlcwQJAG5hbWVfaGFzaACPIsusW0mnAwoAbmV0d29ya19pZFMVNEQKBgBzdGF0ZXMIDQBvbGRfbGVhZl90eXBlBgBzcHJ1Y2UBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:leaves", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmxlYXZlcwQJAG5hbWVfaGFzaACPIsusW0mnAwoAbmV0d29ya19pZKCZEm8KBgBzdGF0ZXMIDQBvbGRfbGVhZl90eXBlBQBiaXJjaAEOAHBlcnNpc3RlbnRfYml0AAEKAHVwZGF0ZV9iaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:leaves", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmxlYXZlcwQJAG5hbWVfaGFzaACPIsusW0mnAwoAbmV0d29ya19pZABprGgKBgBzdGF0ZXMIDQBvbGRfbGVhZl90eXBlBgBqdW5nbGUBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:leaves2", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmxlYXZlczIECQBuYW1lX2hhc2gy/bgrncY1ZAMKAG5ldHdvcmtfaWSFh3olCgYAc3RhdGVzCA0AbmV3X2xlYWZfdHlwZQYAYWNhY2lhAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:leaves2", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmxlYXZlczIECQBuYW1lX2hhc2gy/bgrncY1ZAMKAG5ldHdvcmtfaWTvEAyeCgYAc3RhdGVzCA0AbmV3X2xlYWZfdHlwZQgAZGFya19vYWsBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:mangrove_leaves", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX2xlYXZlcwQJAG5hbWVfaGFzaKyI/dWvhEG8AwoAbmV0d29ya19pZPQxCZ8KBgBzdGF0ZXMBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:cherry_leaves", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9sZWF2ZXMECQBuYW1lX2hhc2giTs9ChhYBlQMKAG5ldHdvcmtfaWR8bPpwCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:azalea_leaves", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmF6YWxlYV9sZWF2ZXMECQBuYW1lX2hhc2iXFhD57wFS7AMKAG5ldHdvcmtfaWTNB/9ECgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:azalea_leaves_flowered", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmF6YWxlYV9sZWF2ZXNfZmxvd2VyZWQECQBuYW1lX2hhc2gs8jxlS/pMrwMKAG5ldHdvcmtfaWQ7W4PyCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:sapling", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWQmoOEvCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUDAG9hawADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:sapling", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWQO8pAmCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUGAHNwcnVjZQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:sapling", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWQDHhokCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUFAGJpcmNoAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:sapling", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWTdQrcyCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUGAGp1bmdsZQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:sapling", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWRCDffNCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUGAGFjYWNpYQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:sapling", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWR0BRzPCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUIAGRhcmtfb2FrAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:mangrove_propagule", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0Om1hbmdyb3ZlX3Byb3BhZ3VsZQQJAG5hbWVfaGFzaJGeox6hkfLFAwoAbmV0d29ya19pZAIpvpYKBgBzdGF0ZXMBBwBoYW5naW5nAAMPAHByb3BhZ3VsZV9zdGFnZQAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:cherry_sapling", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNoZXJyeV9zYXBsaW5nBAkAbmFtZV9oYXNoGrPpNMf1LtcDCgBuZXR3b3JrX2lkypakXQoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:bee_nest", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmJlZV9uZXN0BAkAbmFtZV9oYXNo2R2WBxUHEZIDCgBuZXR3b3JrX2lkiXWLEAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAADCwBob25leV9sZXZlbAAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "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": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1lbG9uX2Jsb2NrBAkAbmFtZV9oYXNoXxSm0iYpAx8DCgBuZXR3b3JrX2lkC9rqygoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:melon_slice" - }, - { - "id": "minecraft:glistering_melon_slice" - }, - { - "id": "minecraft:sweet_berries" - }, - { - "id": "minecraft:glow_berries" - }, - { - "id": "minecraft:pumpkin", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OnB1bXBraW4ECQBuYW1lX2hhc2gc8A3jaSzWbgMKAG5ldHdvcmtfaWRFGA+xCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:carved_pumpkin", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNhcnZlZF9wdW1wa2luBAkAbmFtZV9oYXNoPu1T0MJuG90DCgBuZXR3b3JrX2lkXNNn5QoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:lit_pumpkin", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmxpdF9wdW1wa2luBAkAbmFtZV9oYXNo7gWtEm2uPL0DCgBuZXR3b3JrX2lki8sU4AoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:honeycomb" - }, - { - "id": "minecraft:tallgrass", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnRhbGxncmFzcwQJAG5hbWVfaGFzaC3PXpAXXYswAwoAbmV0d29ya19pZOh33DMKBgBzdGF0ZXMIDwB0YWxsX2dyYXNzX3R5cGUEAGZlcm4AAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:double_plant", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZMx1sfgKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQQAZmVybgEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:tallgrass", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnRhbGxncmFzcwQJAG5hbWVfaGFzaC3PXpAXXYswAwoAbmV0d29ya19pZErptfIKBgBzdGF0ZXMIDwB0YWxsX2dyYXNzX3R5cGUEAHRhbGwAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:double_plant", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZAbadmIKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQUAZ3Jhc3MBDwB1cHBlcl9ibG9ja19iaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:nether_sprouts" - }, - { - "id": "minecraft:fire_coral", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmZpcmVfY29yYWwECQBuYW1lX2hhc2hOHyyECVQVJwMKAG5ldHdvcmtfaWS9vF0UCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:brain_coral", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJyYWluX2NvcmFsBAkAbmFtZV9oYXNoRiWlLCwA2ycDCgBuZXR3b3JrX2lkrjAuhgoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:bubble_coral", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJ1YmJsZV9jb3JhbAQJAG5hbWVfaGFzaJz6rWnl+v2qAwoAbmV0d29ya19pZImIWy0KBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:tube_coral", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnR1YmVfY29yYWwECQBuYW1lX2hhc2iYa8oO/tgk7wMKAG5ldHdvcmtfaWRTfND5CgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:horn_coral", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Omhvcm5fY29yYWwECQBuYW1lX2hhc2iZnRHjZbnLPgMKAG5ldHdvcmtfaWR+GGp8CgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:dead_fire_coral", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfZmlyZV9jb3JhbAQJAG5hbWVfaGFzaEPU6tFy/latAwoAbmV0d29ya19pZNMa7V4KBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:dead_brain_coral", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmRlYWRfYnJhaW5fY29yYWwECQBuYW1lX2hhc2j5L6QJCISvzwMKAG5ldHdvcmtfaWQkKzeiCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:dead_bubble_coral", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmRlYWRfYnViYmxlX2NvcmFsBAkAbmFtZV9oYXNoSTOZ/8wpeNYDCgBuZXR3b3JrX2lka6w9DAoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:dead_tube_coral", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfdHViZV9jb3JhbAQJAG5hbWVfaGFzaJGjNWhlaIJeAwoAbmV0d29ya19pZO3Z0ygKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:dead_horn_coral", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfaG9ybl9jb3JhbAQJAG5hbWVfaGFzaJBkz3qt+g2cAwoAbmV0d29ya19pZBAN+eYKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:coral_fan", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZOg7iS4KBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgMAcmVkAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:coral_fan", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZIDj8HMKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgQAcGluawMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:coral_fan", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZLCJP0kKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgYAcHVycGxlAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:coral_fan", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZFz2ly4KBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgQAYmx1ZQMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:coral_fan", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZE4TgnYKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgYAeWVsbG93AxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:coral_fan_dead", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkdhLQzwoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:coral_fan_dead", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkSi6srQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:coral_fan_dead", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkGiGSzAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:coral_fan_dead", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkmvZKOgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:coral_fan_dead", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lknLw+4QoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:crimson_roots", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNyaW1zb25fcm9vdHMECQBuYW1lX2hhc2j1fWgQLViv5QMKAG5ldHdvcmtfaWRLh5DXCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:warped_roots", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OndhcnBlZF9yb290cwQJAG5hbWVfaGFzaBc3WvbJOLlkAwoAbmV0d29ya19pZNLgDnAKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:yellow_flower", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19mbG93ZXIECQBuYW1lX2hhc2jWbU1pF0OUGAMKAG5ldHdvcmtfaWQgO3hpCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWSqsqQGCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUFAHBvcHB5AAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWTqDajjCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUGAG9yY2hpZAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWT5CjveCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUGAGFsbGl1bQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWTORIBJCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUJAGhvdXN0b25pYQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWTuNhmYCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUJAHR1bGlwX3JlZAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWT0O4nfCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUMAHR1bGlwX29yYW5nZQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWTqkthyCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGULAHR1bGlwX3doaXRlAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRMbBA7CgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUKAHR1bGlwX3BpbmsAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRexMAuCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUFAG94ZXllAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWQgs7BECgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUKAGNvcm5mbG93ZXIAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:red_flower", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRvDuNbCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUSAGxpbHlfb2ZfdGhlX3ZhbGxleQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:double_plant", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZOemRt4KBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQkAc3VuZmxvd2VyAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:double_plant", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZOFugoEKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQcAc3lyaW5nYQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:double_plant", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZN4O+/gKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQQAcm9zZQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:double_plant", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZI3w4GMKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQcAcGFlb25pYQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:pitcher_plant", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnBpdGNoZXJfcGxhbnQECQBuYW1lX2hhc2hRJHzsbDH+SQMKAG5ldHdvcmtfaWRnY76VCgYAc3RhdGVzAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:pink_petals", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfcGV0YWxzBAkAbmFtZV9oYXNo6DQwN9SwV3QDCgBuZXR3b3JrX2lkNWneGgoGAHN0YXRlcwMGAGdyb3d0aAAAAAAIHABtaW5lY3JhZnQ6Y2FyZGluYWxfZGlyZWN0aW9uBQBzb3V0aAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:wither_rose", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OndpdGhlcl9yb3NlBAkAbmFtZV9oYXNoaSKxl3I516gDCgBuZXR3b3JrX2lkATXLPwoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:torchflower", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnRvcmNoZmxvd2VyBAkAbmFtZV9oYXNoL+mHtElwbqQDCgBuZXR3b3JrX2lkI34O+AoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "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/XeXOLAMKAG5ldHdvcmtfaWSUkDtbCgYAc3RhdGVzAxMAdmluZV9kaXJlY3Rpb25fYml0cwAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:weeping_vines", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndlZXBpbmdfdmluZXMECQBuYW1lX2hhc2jrLgLHkQygiwMKAG5ldHdvcmtfaWQ8NHSJCgYAc3RhdGVzAxEAd2VlcGluZ192aW5lc19hZ2UAAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:twisting_vines", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnR3aXN0aW5nX3ZpbmVzBAkAbmFtZV9oYXNoDYR5QgVUQJADCgBuZXR3b3JrX2lk5kYVIQoGAHN0YXRlcwMSAHR3aXN0aW5nX3ZpbmVzX2FnZQAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:waterlily", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OndhdGVybGlseQQJAG5hbWVfaGFzaEHgC4c1SXg0AwoAbmV0d29ya19pZOOerp8KBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:seagrass", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OnNlYWdyYXNzBAkAbmFtZV9oYXNoHSBFtoHdWxIDCgBuZXR3b3JrX2lkd3lhEAoGAHN0YXRlcwgOAHNlYV9ncmFzc190eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:kelp" - }, - { - "id": "minecraft:deadbush", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmRlYWRidXNoBAkAbmFtZV9oYXNoPFODe4IScnYDCgBuZXR3b3JrX2lkVfnl+goGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:bamboo", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmJhbWJvbwQJAG5hbWVfaGFzaBgpGmyzhedCAwoAbmV0d29ya19pZIZv1nYKBgBzdGF0ZXMBBwBhZ2VfYml0AAgQAGJhbWJvb19sZWFmX3NpemUJAG5vX2xlYXZlcwgWAGJhbWJvb19zdGFsa190aGlja25lc3MEAHRoaW4AAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:snow", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OnNub3cECQBuYW1lX2hhc2gVHr5XXdETWAMKAG5ldHdvcmtfaWQ0zCeHCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:ice", - "block_state_b64": "CgAACAQAbmFtZQ0AbWluZWNyYWZ0OmljZQQJAG5hbWVfaGFzaNF26f+uUT29AwoAbmV0d29ya19pZOUMaQYKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:packed_ice", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnBhY2tlZF9pY2UECQBuYW1lX2hhc2hk4bu123ZrFgMKAG5ldHdvcmtfaWTr/ooaCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:blue_ice", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0OmJsdWVfaWNlBAkAbmFtZV9oYXNo+EKxYgFhKcgDCgBuZXR3b3JrX2lkxfsA8goGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:snow_layer", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnNub3dfbGF5ZXIECQBuYW1lX2hhc2hXka6atMYUCQMKAG5ldHdvcmtfaWRCrIPcCgYAc3RhdGVzAQsAY292ZXJlZF9iaXQAAwYAaGVpZ2h0AAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:pointed_dripstone", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnBvaW50ZWRfZHJpcHN0b25lBAkAbmFtZV9oYXNoJMISzmHQgt8DCgBuZXR3b3JrX2lkbWrtYgoGAHN0YXRlcwgTAGRyaXBzdG9uZV90aGlja25lc3MDAHRpcAEHAGhhbmdpbmcBAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:dripstone_block", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRyaXBzdG9uZV9ibG9jawQJAG5hbWVfaGFzaIIXnEqY77YsAwoAbmV0d29ya19pZMZi2kwKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:moss_carpet", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vc3NfY2FycGV0BAkAbmFtZV9oYXNo/NEDxRPTshYDCgBuZXR3b3JrX2lkaGG3QwoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:moss_block", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0Om1vc3NfYmxvY2sECQBuYW1lX2hhc2iovcsPUYX2tgMKAG5ldHdvcmtfaWT3JSbfCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:dirt_with_roots", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRpcnRfd2l0aF9yb290cwQJAG5hbWVfaGFzaLCNDYPviDCIAwoAbmV0d29ya19pZNCkwzoKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:hanging_roots", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Omhhbmdpbmdfcm9vdHMECQBuYW1lX2hhc2jaXn+Y5UZpDAMKAG5ldHdvcmtfaWRU4c2vCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:mangrove_roots", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hbmdyb3ZlX3Jvb3RzBAkAbmFtZV9oYXNoa786PzQGZ6kDCgBuZXR3b3JrX2lklA0AHgoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:muddy_mangrove_roots", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0Om11ZGR5X21hbmdyb3ZlX3Jvb3RzBAkAbmFtZV9oYXNo9YApdHpo1RkDCgBuZXR3b3JrX2lkH0Oc4woGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:big_dripleaf", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJpZ19kcmlwbGVhZgQJAG5hbWVfaGFzaGBEhXjo6qSdAwoAbmV0d29ya19pZMETsb8KBgBzdGF0ZXMBEQBiaWdfZHJpcGxlYWZfaGVhZAEIEQBiaWdfZHJpcGxlYWZfdGlsdAQAbm9uZQgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:small_dripleaf_block", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnNtYWxsX2RyaXBsZWFmX2Jsb2NrBAkAbmFtZV9oYXNojxRAgXP9uWADCgBuZXR3b3JrX2lkozbVPwoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24EAGVhc3QBDwB1cHBlcl9ibG9ja19iaXQBAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:spore_blossom", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnNwb3JlX2Jsb3Nzb20ECQBuYW1lX2hhc2il3U72Gbco2gMKAG5ldHdvcmtfaWSbbbgcCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:azalea", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmF6YWxlYQQJAG5hbWVfaGFzaNyUl+BW9JrBAwoAbmV0d29ya19pZO/XZtQKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:flowering_azalea", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmZsb3dlcmluZ19hemFsZWEECQBuYW1lX2hhc2ie9r33wz8kiwMKAG5ldHdvcmtfaWQ3ij0VCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:glow_lichen", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Omdsb3dfbGljaGVuBAkAbmFtZV9oYXNobyPUrIYlo44DCgBuZXR3b3JrX2lkCh8lSAoGAHN0YXRlcwMZAG11bHRpX2ZhY2VfZGlyZWN0aW9uX2JpdHM/AAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:amethyst_block", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmFtZXRoeXN0X2Jsb2NrBAkAbmFtZV9oYXNob+JK1iiAthcDCgBuZXR3b3JrX2lk8HtpzgoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:budding_amethyst", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmJ1ZGRpbmdfYW1ldGh5c3QECQBuYW1lX2hhc2gJvAwfI14fxgMKAG5ldHdvcmtfaWTQYqfACgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:amethyst_cluster", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmFtZXRoeXN0X2NsdXN0ZXIECQBuYW1lX2hhc2jK82S88Jgm8wMKAG5ldHdvcmtfaWSCPMPGCgYAc3RhdGVzCBQAbWluZWNyYWZ0OmJsb2NrX2ZhY2UCAHVwAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:large_amethyst_bud", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmxhcmdlX2FtZXRoeXN0X2J1ZAQJAG5hbWVfaGFzaAHhdpWD+sd5AwoAbmV0d29ya19pZKkQxOcKBgBzdGF0ZXMIFABtaW5lY3JhZnQ6YmxvY2tfZmFjZQIAdXAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:medium_amethyst_bud", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om1lZGl1bV9hbWV0aHlzdF9idWQECQBuYW1lX2hhc2g5lBGtC0DzZQMKAG5ldHdvcmtfaWSYiP4gCgYAc3RhdGVzCBQAbWluZWNyYWZ0OmJsb2NrX2ZhY2UCAHVwAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:small_amethyst_bud", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnNtYWxsX2FtZXRoeXN0X2J1ZAQJAG5hbWVfaGFzaEnb4+q9PO4YAwoAbmV0d29ya19pZGWzxrQKBgBzdGF0ZXMIFABtaW5lY3JhZnQ6YmxvY2tfZmFjZQIAdXAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "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==" - }, - { - "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/FO78WDoDCgBuZXR3b3JrX2lkLh1OXAoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:red_mushroom", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZF9tdXNocm9vbQQJAG5hbWVfaGFzaPpzJua7669xAwoAbmV0d29ya19pZCvWPYkKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:crimson_fungus", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fZnVuZ3VzBAkAbmFtZV9oYXNolIcCUuFM2u0DCgBuZXR3b3JrX2lkD2NN0QoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:warped_fungus", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9mdW5ndXMECQBuYW1lX2hhc2gq8bSnRVTAFgMKAG5ldHdvcmtfaWTkwS+rCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:brown_mushroom_block", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkdOMhDAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cw4AAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:red_mushroom_block", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnJlZF9tdXNocm9vbV9ibG9jawQJAG5hbWVfaGFzaJTTyJbth9M9AwoAbmV0d29ya19pZM+AyboKBgBzdGF0ZXMDEgBodWdlX211c2hyb29tX2JpdHMOAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:brown_mushroom_block", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkbdt3CAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cw8AAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:brown_mushroom_block", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkSrMl9goGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cwAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:egg" - }, - { - "id": "minecraft:sugar_cane" - }, - { - "id": "minecraft:sugar" - }, - { - "id": "minecraft:rotten_flesh" - }, - { - "id": "minecraft:bone" - }, - { - "id": "minecraft:web", - "block_state_b64": "CgAACAQAbmFtZQ0AbWluZWNyYWZ0OndlYgQJAG5hbWVfaGFzaA4GKQCvG4i9AwoAbmV0d29ya19pZApt+jgKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:spider_eye" - }, - { - "id": "minecraft:mob_spawner", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vYl9zcGF3bmVyBAkAbmFtZV9oYXNoNwGrCV/Fkh8DCgBuZXR3b3JrX2lkM1wTmgoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:monster_egg", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkqXH7RgoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUFAHN0b25lAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:monster_egg", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkeIBb6QoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGULAGNvYmJsZXN0b25lAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:monster_egg", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkDZ2cFQoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGULAHN0b25lX2JyaWNrAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:monster_egg", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkOR/cTAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGURAG1vc3N5X3N0b25lX2JyaWNrAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:monster_egg", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkqdwlHAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUTAGNyYWNrZWRfc3RvbmVfYnJpY2sAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:monster_egg", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkFqqPggoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUUAGNoaXNlbGVkX3N0b25lX2JyaWNrAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:infested_deepslate", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmluZmVzdGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaICF2VYccxF1AwoAbmV0d29ya19pZDa/624KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:dragon_egg", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmRyYWdvbl9lZ2cECQBuYW1lX2hhc2inMzXrV+/e1wMKAG5ldHdvcmtfaWTgO1yRCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:turtle_egg", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnR1cnRsZV9lZ2cECQBuYW1lX2hhc2iwSRcxOJIJ9gMKAG5ldHdvcmtfaWSIRNUhCgYAc3RhdGVzCA0AY3JhY2tlZF9zdGF0ZQkAbm9fY3JhY2tzCBAAdHVydGxlX2VnZ19jb3VudAcAb25lX2VnZwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:sniffer_egg", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnNuaWZmZXJfZWdnBAkAbmFtZV9oYXNoY1lozc8lPcYDCgBuZXR3b3JrX2lk7yb/2QoGAHN0YXRlcwgNAGNyYWNrZWRfc3RhdGUJAG5vX2NyYWNrcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:frog_spawn", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmZyb2dfc3Bhd24ECQBuYW1lX2hhc2iWmd7idp3ZZwMKAG5ldHdvcmtfaWRFzJudCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:pearlescent_froglight", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnBlYXJsZXNjZW50X2Zyb2dsaWdodAQJAG5hbWVfaGFzaKkcFRyycYGyAwoAbmV0d29ya19pZJqYakAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:verdant_froglight", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnZlcmRhbnRfZnJvZ2xpZ2h0BAkAbmFtZV9oYXNoA+eXuTBohrQDCgBuZXR3b3JrX2lkDIVnsQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:ochre_froglight", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om9jaHJlX2Zyb2dsaWdodAQJAG5hbWVfaGFzaMY59kjPe+c3AwoAbmV0d29ya19pZO2TD50KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uATIUAQA=" - }, - { - "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": "CgAACAQAbmFtZRIAbWluZWNyYWZ0Om9ic2lkaWFuBAkAbmFtZV9oYXNoiz4qrb8QjyEDCgBuZXR3b3JrX2lkuqnPpQoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:crying_obsidian", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmNyeWluZ19vYnNpZGlhbgQJAG5hbWVfaGFzaKT0JlA7Z1K+AwoAbmV0d29ya19pZCjbPV4KBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:bedrock", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmJlZHJvY2sECQBuYW1lX2hhc2hWfFrh4LVtxwMKAG5ldHdvcmtfaWT7fKz1CgYAc3RhdGVzAQ4AaW5maW5pYnVybl9iaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:soul_sand", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OnNvdWxfc2FuZAQJAG5hbWVfaGFzaMaf+bccu+KTAwoAbmV0d29ya19pZBQSHrMKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:magma", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0Om1hZ21hBAkAbmFtZV9oYXNoqyTjKaIsWfYDCgBuZXR3b3JrX2lkyfWAZgoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:nether_wart" - }, - { - "id": "minecraft:end_stone", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmVuZF9zdG9uZQQJAG5hbWVfaGFzaH1J9jA39GJNAwoAbmV0d29ya19pZFeFQ7UKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:chorus_flower", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNob3J1c19mbG93ZXIECQBuYW1lX2hhc2iMpSodli5uawMKAG5ldHdvcmtfaWRnd1ZWCgYAc3RhdGVzAwMAYWdlAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:chorus_plant", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmNob3J1c19wbGFudAQJAG5hbWVfaGFzaJhSrmNGKwaMAwoAbmV0d29ya19pZA3uVqMKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:chorus_fruit" - }, - { - "id": "minecraft:popped_chorus_fruit" - }, - { - "id": "minecraft:sponge", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnNwb25nZQQJAG5hbWVfaGFzaLrd2ScYRDMiAwoAbmV0d29ya19pZF01rO0KBgBzdGF0ZXMICwBzcG9uZ2VfdHlwZQMAZHJ5AAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:sponge", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnNwb25nZQQJAG5hbWVfaGFzaLrd2ScYRDMiAwoAbmV0d29ya19pZPiOc4QKBgBzdGF0ZXMICwBzcG9uZ2VfdHlwZQMAd2V0AAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkGnlaAwoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAQgAZGVhZF9iaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkSnHuagoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAQgAZGVhZF9iaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkmkHyegoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUBCABkZWFkX2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkdpUDxgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQBCABkZWFkX2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkYNWvYgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cBCABkZWFkX2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkZSxBQgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAQgAZGVhZF9iaXQBAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lklSTVqQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAQgAZGVhZF9iaXQBAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lk5fTYuQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUBCABkZWFkX2JpdAEAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkwUjqBAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQBCABkZWFkX2JpdAEAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:coral_block", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkq4iWoQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cBCABkZWFkX2JpdAEAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:sculk", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OnNjdWxrBAkAbmFtZV9oYXNo2Lq7T5yQF8kDCgBuZXR3b3JrX2lkyqUPPgoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:sculk_vein", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnNjdWxrX3ZlaW4ECQBuYW1lX2hhc2gJUdhVooV4zwMKAG5ldHdvcmtfaWSUfn1XCgYAc3RhdGVzAxkAbXVsdGlfZmFjZV9kaXJlY3Rpb25fYml0cwAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:sculk_catalyst", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnNjdWxrX2NhdGFseXN0BAkAbmFtZV9oYXNo+gCpbrCHST4DCgBuZXR3b3JrX2lkMJ2n/woGAHN0YXRlcwEFAGJsb29tAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:sculk_shrieker", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnNjdWxrX3Nocmlla2VyBAkAbmFtZV9oYXNo5OXtyObniQ4DCgBuZXR3b3JrX2lkxapoNAoGAHN0YXRlcwEGAGFjdGl2ZQABCgBjYW5fc3VtbW9uAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:sculk_sensor", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnNjdWxrX3NlbnNvcgQJAG5hbWVfaGFzaCkmHreeTgNnAwoAbmV0d29ya19pZLj2WPcKBgBzdGF0ZXMDEgBzY3Vsa19zZW5zb3JfcGhhc2UAAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:calibrated_sculk_sensor", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmNhbGlicmF0ZWRfc2N1bGtfc2Vuc29yBAkAbmFtZV9oYXNoffAcXXN/iJUDCgBuZXR3b3JrX2lkwOx3QQoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAxIAc2N1bGtfc2Vuc29yX3BoYXNlAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:reinforced_deepslate", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnJlaW5mb3JjZWRfZGVlcHNsYXRlBAkAbmFtZV9oYXNoldDmj91EapQDCgBuZXR3b3JrX2lkHIt+aQoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "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+BwwuQoGAHN0YXRlcwgWAHRvcmNoX2ZhY2luZ19kaXJlY3Rpb24HAHVua25vd24AAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:soul_torch", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnNvdWxfdG9yY2gECQBuYW1lX2hhc2huixOT04BRdQMKAG5ldHdvcmtfaWShbFILCgYAc3RhdGVzCBYAdG9yY2hfZmFjaW5nX2RpcmVjdGlvbgcAdW5rbm93bgADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:sea_pickle", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnNlYV9waWNrbGUECQBuYW1lX2hhc2iONEfZJB+glgMKAG5ldHdvcmtfaWSINWQyCgYAc3RhdGVzAw0AY2x1c3Rlcl9jb3VudAAAAAABCABkZWFkX2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:lantern", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmxhbnRlcm4ECQBuYW1lX2hhc2hMw44VI2HWygMKAG5ldHdvcmtfaWRkjQvzCgYAc3RhdGVzAQcAaGFuZ2luZwAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:soul_lantern", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnNvdWxfbGFudGVybgQJAG5hbWVfaGFzaGjIpjxk9z+RAwoAbmV0d29ya19pZGfoP8cKBgBzdGF0ZXMBBwBoYW5naW5nAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:candle", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmNhbmRsZQQJAG5hbWVfaGFzaHPd+MsNdWTfAwoAbmV0d29ya19pZHsBMA0KBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:white_candle", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OndoaXRlX2NhbmRsZQQJAG5hbWVfaGFzaN1EG5Q1mHiEAwoAbmV0d29ya19pZKN1mmgKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:orange_candle", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Om9yYW5nZV9jYW5kbGUECQBuYW1lX2hhc2jySEVWHgUIHQMKAG5ldHdvcmtfaWSfVz82CgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:magenta_candle", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hZ2VudGFfY2FuZGxlBAkAbmFtZV9oYXNoG0u6YIOoBSEDCgBuZXR3b3JrX2lk9xGNkQoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:light_blue_candle", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY2FuZGxlBAkAbmFtZV9oYXNocXGeK0zgrG0DCgBuZXR3b3JrX2lk2m1y8goGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:yellow_candle", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19jYW5kbGUECQBuYW1lX2hhc2i00dtusU3CqQMKAG5ldHdvcmtfaWR9LTmpCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:lime_candle", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmxpbWVfY2FuZGxlBAkAbmFtZV9oYXNokcmrw5xvz7ADCgBuZXR3b3JrX2lkIAUu6QoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:pink_candle", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfY2FuZGxlBAkAbmFtZV9oYXNoQJdEY4sZ0dwDCgBuZXR3b3JrX2lk23Rn5AoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:gray_candle", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXlfY2FuZGxlBAkAbmFtZV9oYXNoS5poSo9wBDEDCgBuZXR3b3JrX2lk3trRCAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:light_gray_candle", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY2FuZGxlBAkAbmFtZV9oYXNo9ruTZLBNMasDCgBuZXR3b3JrX2lkb6DOegoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:cyan_candle", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmN5YW5fY2FuZGxlBAkAbmFtZV9oYXNoc/M8PNVcjOwDCgBuZXR3b3JrX2lkZoIQOQoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:purple_candle", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnBsZV9jYW5kbGUECQBuYW1lX2hhc2jaI3xUW0/myQMKAG5ldHdvcmtfaWSnLI2BCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:blue_candle", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfY2FuZGxlBAkAbmFtZV9oYXNoAASSPW6TgQADCgBuZXR3b3JrX2lkrxrjQAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:brown_candle", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJyb3duX2NhbmRsZQQJAG5hbWVfaGFzaDia0l6s1+WYAwoAbmV0d29ya19pZKSkBXYKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:green_candle", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmdyZWVuX2NhbmRsZQQJAG5hbWVfaGFzaLeFPO1l+fIoAwoAbmV0d29ya19pZBkznDsKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:red_candle", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9jYW5kbGUECQBuYW1lX2hhc2jjAQpGf59ZdwMKAG5ldHdvcmtfaWRbb88GCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:black_candle", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJsYWNrX2NhbmRsZQQJAG5hbWVfaGFzaB+wRDpOqREKAwoAbmV0d29ya19pZNnOnuEKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:crafting_table", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyYWZ0aW5nX3RhYmxlBAkAbmFtZV9oYXNoe76VAmjvbpYDCgBuZXR3b3JrX2lkwCxwaAoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:cartography_table", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmNhcnRvZ3JhcGh5X3RhYmxlBAkAbmFtZV9oYXNomaWiiD/znP8DCgBuZXR3b3JrX2lkI6FzMwoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:fletching_table", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmZsZXRjaGluZ190YWJsZQQJAG5hbWVfaGFzaPFibh8unKyUAwoAbmV0d29ya19pZJ2mW0oKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:smithing_table", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnNtaXRoaW5nX3RhYmxlBAkAbmFtZV9oYXNo4tFES2xOXEYDCgBuZXR3b3JrX2lkXWMBzQoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:beehive", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmJlZWhpdmUECQBuYW1lX2hhc2hCcqn12UbNpwMKAG5ldHdvcmtfaWR/idcaCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAMLAGhvbmV5X2xldmVsAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:suspicious_sand", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnN1c3BpY2lvdXNfc2FuZAQJAG5hbWVfaGFzaL67QsuvLP00AwoAbmV0d29ya19pZKnkaIAKBgBzdGF0ZXMDEABicnVzaGVkX3Byb2dyZXNzAAAAAAEHAGhhbmdpbmcBAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:suspicious_gravel", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN1c3BpY2lvdXNfZ3JhdmVsBAkAbmFtZV9oYXNoJSVbGNk7C3oDCgBuZXR3b3JrX2lkvIEJAAoGAHN0YXRlcwMQAGJydXNoZWRfcHJvZ3Jlc3MAAAAAAQcAaGFuZ2luZwEAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:campfire" - }, - { - "id": "minecraft:soul_campfire" - }, - { - "id": "minecraft:furnace", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmZ1cm5hY2UECQBuYW1lX2hhc2ioOQrludYY8wMKAG5ldHdvcmtfaWRZxnDOCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:blast_furnace", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJsYXN0X2Z1cm5hY2UECQBuYW1lX2hhc2ivDbnjkpGm5QMKAG5ldHdvcmtfaWTcEbV/CgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:smoker", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnNtb2tlcgQJAG5hbWVfaGFzaJd1rDMkRWomAwoAbmV0d29ya19pZGWswMwKBgBzdGF0ZXMIHABtaW5lY3JhZnQ6Y2FyZGluYWxfZGlyZWN0aW9uBQBzb3V0aAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:respawn_anchor", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlc3Bhd25fYW5jaG9yBAkAbmFtZV9oYXNoZOdcjW05qigDCgBuZXR3b3JrX2lkmhMcaQoGAHN0YXRlcwMVAHJlc3Bhd25fYW5jaG9yX2NoYXJnZQAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:brewing_stand" - }, - { - "id": "minecraft:anvil", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lk8Z3VowoGAHN0YXRlcwgGAGRhbWFnZQkAdW5kYW1hZ2VkCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:anvil", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lkpiv8BAoGAHN0YXRlcwgGAGRhbWFnZRAAc2xpZ2h0bHlfZGFtYWdlZAgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:anvil", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lkFu+pdwoGAHN0YXRlcwgGAGRhbWFnZQwAdmVyeV9kYW1hZ2VkCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:grindstone", - "block_state_b64": "CgAACAQAbmFtZRQAbWluZWNyYWZ0OmdyaW5kc3RvbmUECQBuYW1lX2hhc2id56zc0nk99wMKAG5ldHdvcmtfaWS4Es07CgYAc3RhdGVzCAoAYXR0YWNobWVudAgAc3RhbmRpbmcDCQBkaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:enchanting_table", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmVuY2hhbnRpbmdfdGFibGUECQBuYW1lX2hhc2jgIx24VLvMvwMKAG5ldHdvcmtfaWRliFFJCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:bookshelf", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmJvb2tzaGVsZgQJAG5hbWVfaGFzaDU04DrgJCS9AwoAbmV0d29ya19pZBcWwIwKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:chiseled_bookshelf", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX2Jvb2tzaGVsZgQJAG5hbWVfaGFzaNXDBnsIsywYAwoAbmV0d29ya19pZIprt5IKBgBzdGF0ZXMDDABib29rc19zdG9yZWQAAAAAAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:lectern", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmxlY3Rlcm4ECQBuYW1lX2hhc2j5Z4Mmi/1QxAMKAG5ldHdvcmtfaWR4JfDHCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgBCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:cauldron" - }, - { - "id": "minecraft:composter", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmNvbXBvc3RlcgQJAG5hbWVfaGFzaPAADHptzeWJAwoAbmV0d29ya19pZHIL6i4KBgBzdGF0ZXMDFABjb21wb3N0ZXJfZmlsbF9sZXZlbAAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:chest", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmNoZXN0BAkAbmFtZV9oYXNog9ozMxlcA88DCgBuZXR3b3JrX2lkDkOFvAoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:trapped_chest", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnRyYXBwZWRfY2hlc3QECQBuYW1lX2hhc2g2qpF9stsEjgMKAG5ldHdvcmtfaWTjJWYxCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAbm9ydGgAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:ender_chest", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmVuZGVyX2NoZXN0BAkAbmFtZV9oYXNohEZzOFdg0WUDCgBuZXR3b3JrX2lkx4jiSQoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:barrel", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmJhcnJlbAQJAG5hbWVfaGFzaHDkRPGymiRqAwoAbmV0d29ya19pZPnxzgsKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:undyed_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnVuZHllZF9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaOC9mypm/MlBAwoAbmV0d29ya19pZJ8rxp0KBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:white_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OndoaXRlX3NodWxrZXJfYm94BAkAbmFtZV9oYXNosK79m1rPUBwDCgBuZXR3b3JrX2lkjrET6goGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:light_gray_shulker_box", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2iBe5zq7PxHmgMKAG5ldHdvcmtfaWSCVJv0CgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:gray_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmdyYXlfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2ga2s8ctjHUhgMKAG5ldHdvcmtfaWS3WMsWCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:black_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmJsYWNrX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoPm03OZphrp8DCgBuZXR3b3JrX2lkXHztNAoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:brown_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmJyb3duX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoT3DD6qAL9cADCgBuZXR3b3JrX2lkaXxpYQoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:red_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OnJlZF9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaMIlKSCzqSZoAwoAbmV0d29ya19pZNrf+icKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:orange_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0Om9yYW5nZV9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaG2MAXU67wGrAwoAbmV0d29ya19pZGoO05gKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:yellow_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnllbGxvd19zaHVsa2VyX2JveAQJAG5hbWVfaGFzaIsLwQHYjcIEAwoAbmV0d29ya19pZBCBSiYKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:lime_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmxpbWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2hUwBkg+faUGAMKAG5ldHdvcmtfaWRJeKqqCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:green_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmdyZWVuX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoZgUeT3LupLUDCgBuZXR3b3JrX2lkzJiohQoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:cyan_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmN5YW5fc2h1bGtlcl9ib3gECQBuYW1lX2hhc2gSfbjteXg5yAMKAG5ldHdvcmtfaWTHeliECgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:light_blue_shulker_box", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2h0VFCX0qsRxQMKAG5ldHdvcmtfaWQXD8U0CgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:blue_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmJsdWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2hn9gS0XIe6rAMKAG5ldHdvcmtfaWTO4PJaCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:purple_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRwAbWluZWNyYWZ0OnB1cnBsZV9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaEV/lkNPxRDdAwoAbmV0d29ya19pZFK25GAKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:magenta_shulker_box", - "block_state_b64": "CgAACAQAbmFtZR0AbWluZWNyYWZ0Om1hZ2VudGFfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2iqWM7IJHxcFgMKAG5ldHdvcmtfaWTyyudTCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:pink_shulker_box", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OnBpbmtfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2in1tkJ1GNcZgMKAG5ldHdvcmtfaWQOEGXjCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:armor_stand" - }, - { - "id": "minecraft:noteblock", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0Om5vdGVibG9jawQJAG5hbWVfaGFzaHPA8dBBH0UaAwoAbmV0d29ya19pZH1U5QkKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:jukebox", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0Omp1a2Vib3gECQBuYW1lX2hhc2ieAIPExf/ZfgMKAG5ldHdvcmtfaWSmR7JfCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "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": "CgAACAQAbmFtZRMAbWluZWNyYWZ0Omdsb3dzdG9uZQQJAG5hbWVfaGFzaFYqXNkefIlPAwoAbmV0d29ya19pZGT7WYYKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:redstone_lamp", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZHN0b25lX2xhbXAECQBuYW1lX2hhc2hJ9V80caPvEgMKAG5ldHdvcmtfaWRvNPwnCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:sea_lantern", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OnNlYV9sYW50ZXJuBAkAbmFtZV9oYXNoLPsv1TX9M+QDCgBuZXR3b3JrX2lk1PPVyAoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "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": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OmJlYWNvbgQJAG5hbWVfaGFzaACwhhfSkdkHAwoAbmV0d29ya19pZF8jfiEKBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:bell", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0OmJlbGwECQBuYW1lX2hhc2iPqsgDXRcsxAMKAG5ldHdvcmtfaWT7zhOoCgYAc3RhdGVzCAoAYXR0YWNobWVudAgAc3RhbmRpbmcDCQBkaXJlY3Rpb24AAAAAAQoAdG9nZ2xlX2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:conduit", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmNvbmR1aXQECQBuYW1lX2hhc2jqxKAxq2EaWQMKAG5ldHdvcmtfaWTWcBVnCgYAc3RhdGVzAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:stonecutter_block", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lY3V0dGVyX2Jsb2NrBAkAbmFtZV9oYXNoQAXTbAM3MeYDCgBuZXR3b3JrX2lkWS4RjAoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:end_portal_frame", - "block_state_b64": "CgAACAQAbmFtZRoAbWluZWNyYWZ0OmVuZF9wb3J0YWxfZnJhbWUECQBuYW1lX2hhc2gqofyUIjGOpQMKAG5ldHdvcmtfaWRbGHf8CgYAc3RhdGVzARIAZW5kX3BvcnRhbF9leWVfYml0AAgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "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/q5cEA0hmQMKAG5ldHdvcmtfaWQ2eM8kCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:lightning_rod", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmxpZ2h0bmluZ19yb2QECQBuYW1lX2hhc2ioXQF1xvfHNQMKAG5ldHdvcmtfaWRLuHyACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "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+Sp6YCgYAc3RhdGVzAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:golden_rail", - "block_state_b64": "CgAACAQAbmFtZRUAbWluZWNyYWZ0OmdvbGRlbl9yYWlsBAkAbmFtZV9oYXNoOoV5MaKipoUDCgBuZXR3b3JrX2lkfAcxLwoGAHN0YXRlcwENAHJhaWxfZGF0YV9iaXQAAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:detector_rail", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmRldGVjdG9yX3JhaWwECQBuYW1lX2hhc2gVUk31qOysUQMKAG5ldHdvcmtfaWRVW/aICgYAc3RhdGVzAQ0AcmFpbF9kYXRhX2JpdAADDgByYWlsX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:activator_rail", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmFjdGl2YXRvcl9yYWlsBAkAbmFtZV9oYXNosIL91qriCRkDCgBuZXR3b3JrX2lkZfckmwoGAHN0YXRlcwENAHJhaWxfZGF0YV9iaXQAAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "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": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZHN0b25lX2Jsb2NrBAkAbmFtZV9oYXNoRhULL0r8o0sDCgBuZXR3b3JrX2lklayOHgoGAHN0YXRlcwADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:redstone_torch", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZHN0b25lX3RvcmNoBAkAbmFtZV9oYXNoizFRjpYMIDgDCgBuZXR3b3JrX2lkuHz7yAoGAHN0YXRlcwgWAHRvcmNoX2ZhY2luZ19kaXJlY3Rpb24HAHVua25vd24AAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:lever", - "block_state_b64": "CgAACAQAbmFtZQ8AbWluZWNyYWZ0OmxldmVyBAkAbmFtZV9oYXNoGMJeLJsUMLYDCgBuZXR3b3JrX2lkEF/GuAoGAHN0YXRlcwgPAGxldmVyX2RpcmVjdGlvbg4AZG93bl9lYXN0X3dlc3QBCABvcGVuX2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:wooden_button", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Ondvb2Rlbl9idXR0b24ECQBuYW1lX2hhc2hR7PgSTQt0sQMKAG5ldHdvcmtfaWSU07kYCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:spruce_button", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9idXR0b24ECQBuYW1lX2hhc2jBW9Z8aYE7YQMKAG5ldHdvcmtfaWTkUIGuCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:birch_button", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX2J1dHRvbgQJAG5hbWVfaGFzaJXYgGuSHbTwAwoAbmV0d29ya19pZGWp3yoKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:jungle_button", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9idXR0b24ECQBuYW1lX2hhc2iCgNANcJs+BQMKAG5ldHdvcmtfaWT9fImWCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:acacia_button", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9idXR0b24ECQBuYW1lX2hhc2gVvmcT7LTO0wMKAG5ldHdvcmtfaWRQnxIJCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:dark_oak_button", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX2J1dHRvbgQJAG5hbWVfaGFzaIV10ZGGrCIEAwoAbmV0d29ya19pZN5vAmIKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:mangrove_button", - "block_state_b64": "CgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX2J1dHRvbgQJAG5hbWVfaGFzaNzeYYKLgOzJAwoAbmV0d29ya19pZAFEGQ0KBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:cherry_button", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9idXR0b24ECQBuYW1lX2hhc2j2/IHjeAbUcwMKAG5ldHdvcmtfaWRJ1irQCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:bamboo_button", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19idXR0b24ECQBuYW1lX2hhc2j7AddMi+6nsgMKAG5ldHdvcmtfaWSa9w4/CgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:stone_button", - "block_state_b64": "CgAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX2J1dHRvbgQJAG5hbWVfaGFzaM4ejMctmvohAwoAbmV0d29ya19pZMw+aC0KBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:crimson_button", - "block_state_b64": "CgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fYnV0dG9uBAkAbmFtZV9oYXNofnjYHaYIeWgDCgBuZXR3b3JrX2lk+n1vyQoGAHN0YXRlcwESAGJ1dHRvbl9wcmVzc2VkX2JpdAADEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:warped_button", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9idXR0b24ECQBuYW1lX2hhc2jwkV2EU6Cn1QMKAG5ldHdvcmtfaWTnHnk1CgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:polished_blackstone_button", - "block_state_b64": "CgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnV0dG9uBAkAbmFtZV9oYXNojmxzQKS0S/EDCgBuZXR3b3JrX2lkDtQ95woGAHN0YXRlcwESAGJ1dHRvbl9wcmVzc2VkX2JpdAADEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:tripwire_hook", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnRyaXB3aXJlX2hvb2sECQBuYW1lX2hhc2gQdp+oGZLNnAMKAG5ldHdvcmtfaWSy+1KJCgYAc3RhdGVzAQwAYXR0YWNoZWRfYml0AAMJAGRpcmVjdGlvbgAAAAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:wooden_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0Ondvb2Rlbl9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaGkGs5kCuA74AwoAbmV0d29ya19pZDRzPNwKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:spruce_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OnNwcnVjZV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaNmwuq549fJKAwoAbmV0d29ya19pZLQMCw0KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:birch_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OmJpcmNoX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNorQkT9kDdlTwDCgBuZXR3b3JrX2lkH0G97AoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:jungle_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0Omp1bmdsZV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaJ7DcteCkb8/AwoAbmV0d29ya19pZLdPBSAKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:acacia_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmFjYWNpYV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaC2frZtfoYqCAwoAbmV0d29ya19pZIDdI18KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:dark_oak_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0OmRhcmtfb2FrX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoHUCJsTy52pwDCgBuZXR3b3JrX2lkKpi8rAoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:mangrove_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZSEAbWluZWNyYWZ0Om1hbmdyb3ZlX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoiDsTfJaX100DCgBuZXR3b3JrX2lkuwWDyQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:cherry_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmNoZXJyeV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaALMqYEZDUQHAwoAbmV0d29ya19pZPNT+r0KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:bamboo_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OmJhbWJvb19wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaNvxJ7NIAaqlAwoAbmV0d29ya19pZIZ8XnYKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:crimson_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZSAAbWluZWNyYWZ0OmNyaW1zb25fcHJlc3N1cmVfcGxhdGUECQBuYW1lX2hhc2hqBDVDAd31/gMKAG5ldHdvcmtfaWRmV18LCgYAc3RhdGVzAw8AcmVkc3RvbmVfc2lnbmFsAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:warped_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR8AbWluZWNyYWZ0OndhcnBlZF9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaBxFoQksWtYUAwoAbmV0d29ya19pZJVRoIcKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:stone_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZR4AbWluZWNyYWZ0OnN0b25lX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNounJuTBUTrU8DCgBuZXR3b3JrX2lkjDydwQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:light_weighted_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X3dlaWdodGVkX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoOyOJkNxLtkEDCgBuZXR3b3JrX2lkrr2AjgoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:heavy_weighted_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZScAbWluZWNyYWZ0OmhlYXZ5X3dlaWdodGVkX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoltgDmDvTajUDCgBuZXR3b3JrX2lkFxVKuQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:polished_blackstone_pressure_plate", - "block_state_b64": "CgAACAQAbmFtZSwAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfcHJlc3N1cmVfcGxhdGUECQBuYW1lX2hhc2h65Ci6/CeGqwMKAG5ldHdvcmtfaWTaSW5xCgYAc3RhdGVzAw8AcmVkc3RvbmVfc2lnbmFsAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:observer", - "block_state_b64": "CgAACAQAbmFtZRIAbWluZWNyYWZ0Om9ic2VydmVyBAkAbmFtZV9oYXNoYhlh1lpmHTgDCgBuZXR3b3JrX2lkQEh55goGAHN0YXRlcwgaAG1pbmVjcmFmdDpmYWNpbmdfZGlyZWN0aW9uBABkb3duAQsAcG93ZXJlZF9iaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:daylight_detector", - "block_state_b64": "CgAACAQAbmFtZRsAbWluZWNyYWZ0OmRheWxpZ2h0X2RldGVjdG9yBAkAbmFtZV9oYXNoV0F0s7B7PVgDCgBuZXR3b3JrX2lkri5afQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:repeater" - }, - { - "id": "minecraft:comparator" - }, - { - "id": "minecraft:hopper" - }, - { - "id": "minecraft:dropper", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmRyb3BwZXIECQBuYW1lX2hhc2joXP7XqU0l3QMKAG5ldHdvcmtfaWQfQN6zCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgMAAAABDQB0cmlnZ2VyZWRfYml0AAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:dispenser", - "block_state_b64": "CgAACAQAbmFtZRMAbWluZWNyYWZ0OmRpc3BlbnNlcgQJAG5hbWVfaGFzaP1RR+zAbYP2AwoAbmV0d29ya19pZGAayD0KBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAwAAAAENAHRyaWdnZXJlZF9iaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:crafter", - "block_state_b64": "CgAACAQAbmFtZREAbWluZWNyYWZ0OmNyYWZ0ZXIECQBuYW1lX2hhc2iLCT/rJmRN8QMKAG5ldHdvcmtfaWTPTbvrCgYAc3RhdGVzAQgAY3JhZnRpbmcACAsAb3JpZW50YXRpb24JAGRvd25fZWFzdAENAHRyaWdnZXJlZF9iaXQAAAMHAHZlcnNpb24BMhQBAA==" - }, - { - "id": "minecraft:piston", - "block_state_b64": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnBpc3RvbgQJAG5hbWVfaGFzaDs3AFh1fL0uAwoAbmV0d29ya19pZLD/5XQKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAQAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "id": "minecraft:sticky_piston", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OnN0aWNreV9waXN0b24ECQBuYW1lX2hhc2hPFJFJSiJ0ZQMKAG5ldHdvcmtfaWT/MzCJCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgEAAAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:tnt", - "block_state_b64": "CgAACAQAbmFtZQ0AbWluZWNyYWZ0OnRudAQJAG5hbWVfaGFzaEYOHwCvJH29AwoAbmV0d29ya19pZCGfjU4KBgBzdGF0ZXMBFABhbGxvd191bmRlcndhdGVyX2JpdAABCwBleHBsb2RlX2JpdAAAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:name_tag" - }, - { - "id": "minecraft:loom", - "block_state_b64": "CgAACAQAbmFtZQ4AbWluZWNyYWZ0Omxvb20ECQBuYW1lX2hhc2i7DKjAXNq8TAMKAG5ldHdvcmtfaWR/49HXCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "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": "CgAACAQAbmFtZRAAbWluZWNyYWZ0OnRhcmdldAQJAG5hbWVfaGFzaJc66SVbYlaxAwoAbmV0d29ya19pZPBozs0KBgBzdGF0ZXMAAwcAdmVyc2lvbgEyFAEA" - }, - { - "id": "minecraft:decorated_pot", - "block_state_b64": "CgAACAQAbmFtZRcAbWluZWNyYWZ0OmRlY29yYXRlZF9wb3QECQBuYW1lX2hhc2jjQgckn8VTvwMKAG5ldHdvcmtfaWRwvkUUCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uATIUAQA=" - }, - { - "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_60.json b/core/src/main/resources/bedrock/creative_items.1_20_60.json deleted file mode 100644 index d4063030e..000000000 --- a/core/src/main/resources/bedrock/creative_items.1_20_60.json +++ /dev/null @@ -1,5787 +0,0 @@ -{ - "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/creative_items.1_20_70.json b/core/src/main/resources/bedrock/creative_items.1_21_0.json similarity index 78% rename from core/src/main/resources/bedrock/creative_items.1_20_70.json rename to core/src/main/resources/bedrock/creative_items.1_21_0.json index ed498b782..4bd0ab60e 100644 --- a/core/src/main/resources/bedrock/creative_items.1_20_70.json +++ b/core/src/main/resources/bedrock/creative_items.1_21_0.json @@ -2,443 +2,443 @@ "items": [ { "id": "minecraft:oak_planks", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQFAAAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19wbGFua3MECQBuYW1lX2hhc2ilMDLR92rQ4wMKAG5ldHdvcmtfaWS2GotyCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQFAAAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19wbGFua3MECQBuYW1lX2hhc2ilMDLR92rQ4wMKAG5ldHdvcmtfaWS2GotyCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:spruce_planks", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAwAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9wbGFua3MECQBuYW1lX2hhc2iumBkmFGFE8gMKAG5ldHdvcmtfaWSo8TFgCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAwAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9wbGFua3MECQBuYW1lX2hhc2iumBkmFGFE8gMKAG5ldHdvcmtfaWSo8TFgCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:birch_planks", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX3BsYW5rcwQJAG5hbWVfaGFzaLrrAKJqV2WFAwoAbmV0d29ya19pZL+e3ZAKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX3BsYW5rcwQJAG5hbWVfaGFzaLrrAKJqV2WFAwoAbmV0d29ya19pZL+e3ZAKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:jungle_planks", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAwAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9wbGFua3MECQBuYW1lX2hhc2iBM3k4T3FAugMKAG5ldHdvcmtfaWSXUmBCCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAwAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9wbGFua3MECQBuYW1lX2hhc2iBM3k4T3FAugMKAG5ldHdvcmtfaWSXUmBCCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:acacia_planks", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAwAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9wbGFua3MECQBuYW1lX2hhc2g60edJxO5/aAMKAG5ldHdvcmtfaWTUXozECgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAwAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9wbGFua3MECQBuYW1lX2hhc2g60edJxO5/aAMKAG5ldHdvcmtfaWTUXozECgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:dark_oak_planks", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTmAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX3BsYW5rcwQJAG5hbWVfaGFzaAr64wkQ9cA7AwoAbmV0d29ya19pZFbMeR0KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTmAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX3BsYW5rcwQJAG5hbWVfaGFzaAr64wkQ9cA7AwoAbmV0d29ya19pZFbMeR0KBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:mangrove_planks", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX3BsYW5rcwQJAG5hbWVfaGFzaPvLtcEA0F8xAwoAbmV0d29ya19pZEvnlCYKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX3BsYW5rcwQJAG5hbWVfaGFzaPvLtcEA0F8xAwoAbmV0d29ya19pZEvnlCYKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:cherry_planks", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9wbGFua3MECQBuYW1lX2hhc2hNIvVh/lVW7gMKAG5ldHdvcmtfaWQTXpRoCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9wbGFua3MECQBuYW1lX2hhc2hNIvVh/lVW7gMKAG5ldHdvcmtfaWQTXpRoCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:bamboo_planks", - "block_state_b64": "CgAAAwgAYmxvY2tfaWT9AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19wbGFua3MECQBuYW1lX2hhc2gYnjNz7SCCjgMKAG5ldHdvcmtfaWTi8ySSCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWT9AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19wbGFua3MECQBuYW1lX2hhc2gYnjNz7SCCjgMKAG5ldHdvcmtfaWTi8ySSCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:bamboo_mosaic", - "block_state_b64": "CgAAAwgAYmxvY2tfaWT8AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19tb3NhaWMECQBuYW1lX2hhc2izSEgiMKOp/AMKAG5ldHdvcmtfaWQZ/p8xCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWT8AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19tb3NhaWMECQBuYW1lX2hhc2izSEgiMKOp/AMKAG5ldHdvcmtfaWQZ/p8xCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:crimson_planks", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTxAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fcGxhbmtzBAkAbmFtZV9oYXNoJc5IKqNXJnwDCgBuZXR3b3JrX2lkwtJDdQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTxAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fcGxhbmtzBAkAbmFtZV9oYXNoJc5IKqNXJnwDCgBuZXR3b3JrX2lkwtJDdQoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:warped_planks", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTyAQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9wbGFua3MECQBuYW1lX2hhc2g3yGXEWhe6LgMKAG5ldHdvcmtfaWStTABvCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTyAQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9wbGFua3MECQBuYW1lX2hhc2g3yGXEWhe6LgMKAG5ldHdvcmtfaWStTABvCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSE4JosCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCwBjb2JibGVzdG9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSE4JosCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCwBjb2JibGVzdG9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWTUvV6XCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEQBtb3NzeV9jb2JibGVzdG9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWTUvV6XCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEQBtb3NzeV9jb2JibGVzdG9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWT4opb2CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBwBncmFuaXRlCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWT4opb2CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBwBncmFuaXRlCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQAMQTVCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBwBkaW9yaXRlCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQAMQTVCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBwBkaW9yaXRlCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQIbDOcCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCABhbmRlc2l0ZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQIbDOcCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCABhbmRlc2l0ZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSZKhusCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCQBzYW5kc3RvbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSZKhusCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCQBzYW5kc3RvbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSp4zgCCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlDQByZWRfc2FuZHN0b25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSp4zgCCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlDQByZWRfc2FuZHN0b25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRbqVHTCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCwBzdG9uZV9icmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRbqVHTCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCwBzdG9uZV9icmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRr0ZT/CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEQBtb3NzeV9zdG9uZV9icmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRr0ZT/CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEQBtb3NzeV9zdG9uZV9icmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRnLis3CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBQBicmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRnLis3CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBQBicmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQNLzfSCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlDABuZXRoZXJfYnJpY2sIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQNLzfSCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlDABuZXRoZXJfYnJpY2sIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQ5h0xwCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEAByZWRfbmV0aGVyX2JyaWNrCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQ5h0xwCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEAByZWRfbmV0aGVyX2JyaWNrCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWS9J0B2CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCQBlbmRfYnJpY2sIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWS9J0B2CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCQBlbmRfYnJpY2sIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:cobblestone_wall", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRPbkJeCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCgBwcmlzbWFyaW5lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRPbkJeCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCgBwcmlzbWFyaW5lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:blackstone_wall", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQUAgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsYWNrc3RvbmVfd2FsbAQJAG5hbWVfaGFzaMP8XppUSU1RAwoAbmV0d29ya19pZMbeBBsKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQUAgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsYWNrc3RvbmVfd2FsbAQJAG5hbWVfaGFzaMP8XppUSU1RAwoAbmV0d29ya19pZMbeBBsKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:polished_blackstone_wall", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQoAgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfd2FsbAQJAG5hbWVfaGFzaP6SwV08YwzAAwoAbmV0d29ya19pZAJLsz8KBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQoAgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfd2FsbAQJAG5hbWVfaGFzaP6SwV08YwzAAwoAbmV0d29ya19pZAJLsz8KBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:polished_blackstone_brick_wall", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQVAgAACAQAbmFtZSgAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfd2FsbAQJAG5hbWVfaGFzaBBIDZbHxiEzAwoAbmV0d29ya19pZEbLV8cKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQVAgAACAQAbmFtZSgAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfd2FsbAQJAG5hbWVfaGFzaBBIDZbHxiEzAwoAbmV0d29ya19pZEbLV8cKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:cobbled_deepslate_wall", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR9AgAACAQAbmFtZSAAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3dhbGwECQBuYW1lX2hhc2iECY5oKxeT+gMKAG5ldHdvcmtfaWRCnPrFCgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR9AgAACAQAbmFtZSAAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3dhbGwECQBuYW1lX2hhc2iECY5oKxeT+gMKAG5ldHdvcmtfaWRCnPrFCgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:deepslate_tile_wall", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3dhbGwECQBuYW1lX2hhc2jz7N+PeuEXgQMKAG5ldHdvcmtfaWTqw4s4CgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3dhbGwECQBuYW1lX2hhc2jz7N+PeuEXgQMKAG5ldHdvcmtfaWTqw4s4CgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:polished_deepslate_wall", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV93YWxsBAkAbmFtZV9oYXNoHxjTdj9pevMDCgBuZXR3b3JrX2lkIvBYYwoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV93YWxsBAkAbmFtZV9oYXNoHxjTdj9pevMDCgBuZXR3b3JrX2lkIvBYYwoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:deepslate_brick_wall", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSJAgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja193YWxsBAkAbmFtZV9oYXNoEs3EQrjroyEDCgBuZXR3b3JrX2lkwlrCGwoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSJAgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja193YWxsBAkAbmFtZV9oYXNoEs3EQrjroyEDCgBuZXR3b3JrX2lkwlrCGwoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:mud_brick_wall", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAgAACAQAbmFtZRgAbWluZWNyYWZ0Om11ZF9icmlja193YWxsBAkAbmFtZV9oYXNov9b98ATpUSwDCgBuZXR3b3JrX2lkH/1WZQoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAgAACAQAbmFtZRgAbWluZWNyYWZ0Om11ZF9icmlja193YWxsBAkAbmFtZV9oYXNov9b98ATpUSwDCgBuZXR3b3JrX2lkH/1WZQoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:oak_fence", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRVAAAACAQAbmFtZRMAbWluZWNyYWZ0Om9ha19mZW5jZQQJAG5hbWVfaGFzaGEmid7AaCWRAwoAbmV0d29ya19pZDvPEXcKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRVAAAACAQAbmFtZRMAbWluZWNyYWZ0Om9ha19mZW5jZQQJAG5hbWVfaGFzaGEmid7AaCWRAwoAbmV0d29ya19pZDvPEXcKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:spruce_fence", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRCAwAACAQAbmFtZRYAbWluZWNyYWZ0OnNwcnVjZV9mZW5jZQQJAG5hbWVfaGFzaPQCm+aX1ZQeAwoAbmV0d29ya19pZD1QUEoKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRCAwAACAQAbmFtZRYAbWluZWNyYWZ0OnNwcnVjZV9mZW5jZQQJAG5hbWVfaGFzaPQCm+aX1ZQeAwoAbmV0d29ya19pZD1QUEoKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:birch_fence", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ/AwAACAQAbmFtZRUAbWluZWNyYWZ0OmJpcmNoX2ZlbmNlBAkAbmFtZV9oYXNo6CJ2ATpANfgDCgBuZXR3b3JrX2lkmCUV2QoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ/AwAACAQAbmFtZRUAbWluZWNyYWZ0OmJpcmNoX2ZlbmNlBAkAbmFtZV9oYXNo6CJ2ATpANfgDCgBuZXR3b3JrX2lkmCUV2QoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:jungle_fence", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRBAwAACAQAbmFtZRYAbWluZWNyYWZ0Omp1bmdsZV9mZW5jZQQJAG5hbWVfaGFzaOX4cD9uAmsdAwoAbmV0d29ya19pZHz1VxkKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRBAwAACAQAbmFtZRYAbWluZWNyYWZ0Omp1bmdsZV9mZW5jZQQJAG5hbWVfaGFzaOX4cD9uAmsdAwoAbmV0d29ya19pZHz1VxkKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:acacia_fence", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ+AwAACAQAbmFtZRYAbWluZWNyYWZ0OmFjYWNpYV9mZW5jZQQJAG5hbWVfaGFzaGjn+RlKVDH6AwoAbmV0d29ya19pZNVGubwKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ+AwAACAQAbmFtZRYAbWluZWNyYWZ0OmFjYWNpYV9mZW5jZQQJAG5hbWVfaGFzaGjn+RlKVDH6AwoAbmV0d29ya19pZNVGubwKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:dark_oak_fence", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRAAwAACAQAbmFtZRgAbWluZWNyYWZ0OmRhcmtfb2FrX2ZlbmNlBAkAbmFtZV9oYXNoGPj0gCgM0c0DCgBuZXR3b3JrX2lk2w+gEwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRAAwAACAQAbmFtZRgAbWluZWNyYWZ0OmRhcmtfb2FrX2ZlbmNlBAkAbmFtZV9oYXNoGPj0gCgM0c0DCgBuZXR3b3JrX2lk2w+gEwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:mangrove_fence", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTqAgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hbmdyb3ZlX2ZlbmNlBAkAbmFtZV9oYXNowwAd7tPu9bsDCgBuZXR3b3JrX2lkKEcd0goGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTqAgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hbmdyb3ZlX2ZlbmNlBAkAbmFtZV9oYXNowwAd7tPu9bsDCgBuZXR3b3JrX2lkKEcd0goGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:cherry_fence", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAwAACAQAbmFtZRYAbWluZWNyYWZ0OmNoZXJyeV9mZW5jZQQJAG5hbWVfaGFzaFmtUfHfTxcxAwoAbmV0d29ya19pZPCBxAIKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAwAACAQAbmFtZRYAbWluZWNyYWZ0OmNoZXJyeV9mZW5jZQQJAG5hbWVfaGFzaFmtUfHfTxcxAwoAbmV0d29ya19pZPCBxAIKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:bamboo_fence", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJhbWJvb19mZW5jZQQJAG5hbWVfaGFzaCKRbxfXsfkiAwoAbmV0d29ya19pZJNXKFcKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJhbWJvb19mZW5jZQQJAG5hbWVfaGFzaCKRbxfXsfkiAwoAbmV0d29ya19pZJNXKFcKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:nether_brick_fence", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRxAAAACAQAbmFtZRwAbWluZWNyYWZ0Om5ldGhlcl9icmlja19mZW5jZQQJAG5hbWVfaGFzaA6030ngawxcAwoAbmV0d29ya19pZLnjLF4KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRxAAAACAQAbmFtZRwAbWluZWNyYWZ0Om5ldGhlcl9icmlja19mZW5jZQQJAG5hbWVfaGFzaA6030ngawxcAwoAbmV0d29ya19pZLnjLF4KBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:crimson_fence", - "block_state_b64": "CgAAAwgAYmxvY2tfaWT/AQAACAQAbmFtZRcAbWluZWNyYWZ0OmNyaW1zb25fZmVuY2UECQBuYW1lX2hhc2jhUhKv1HGj9AMKAG5ldHdvcmtfaWR3OH3OCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWT/AQAACAQAbmFtZRcAbWluZWNyYWZ0OmNyaW1zb25fZmVuY2UECQBuYW1lX2hhc2jhUhKv1HGj9AMKAG5ldHdvcmtfaWR3OH3OCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:warped_fence", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQAAgAACAQAbmFtZRYAbWluZWNyYWZ0OndhcnBlZF9mZW5jZQQJAG5hbWVfaGFzaJfb3/YuKmOWAwoAbmV0d29ya19pZCpaGC8KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQAAgAACAQAbmFtZRYAbWluZWNyYWZ0OndhcnBlZF9mZW5jZQQJAG5hbWVfaGFzaJfb3/YuKmOWAwoAbmV0d29ya19pZCpaGC8KBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:fence_gate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRrAAAACAQAbmFtZRQAbWluZWNyYWZ0OmZlbmNlX2dhdGUECQBuYW1lX2hhc2hTxpjEDmRzAwMKAG5ldHdvcmtfaWR+T9kTCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRrAAAACAQAbmFtZRQAbWluZWNyYWZ0OmZlbmNlX2dhdGUECQBuYW1lX2hhc2hTxpjEDmRzAwMKAG5ldHdvcmtfaWR+T9kTCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:spruce_fence_gate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWS3AAAACAQAbmFtZRsAbWluZWNyYWZ0OnNwcnVjZV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoanTVB84HRbkDCgBuZXR3b3JrX2lkEnw5egoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWS3AAAACAQAbmFtZRsAbWluZWNyYWZ0OnNwcnVjZV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoanTVB84HRbkDCgBuZXR3b3JrX2lkEnw5egoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:birch_fence_gate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWS4AAAACAQAbmFtZRoAbWluZWNyYWZ0OmJpcmNoX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2jmfPklI8azSwMKAG5ldHdvcmtfaWQL77/BCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWS4AAAACAQAbmFtZRoAbWluZWNyYWZ0OmJpcmNoX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2jmfPklI8azSwMKAG5ldHdvcmtfaWQL77/BCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:jungle_fence_gate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWS5AAAACAQAbmFtZRsAbWluZWNyYWZ0Omp1bmdsZV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNobYVQkfBomIcDCgBuZXR3b3JrX2lkA1zgtgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWS5AAAACAQAbmFtZRsAbWluZWNyYWZ0Omp1bmdsZV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNobYVQkfBomIcDCgBuZXR3b3JrX2lkA1zgtgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:acacia_fence_gate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWS7AAAACAQAbmFtZRsAbWluZWNyYWZ0OmFjYWNpYV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoZnrLUx/XSekDCgBuZXR3b3JrX2lkHg/kTgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWS7AAAACAQAbmFtZRsAbWluZWNyYWZ0OmFjYWNpYV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoZnrLUx/XSekDCgBuZXR3b3JrX2lkHg/kTgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:dark_oak_fence_gate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWS6AAAACAQAbmFtZR0AbWluZWNyYWZ0OmRhcmtfb2FrX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2j2PTvdJJHcVQMKAG5ldHdvcmtfaWTwjOCeCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWS6AAAACAQAbmFtZR0AbWluZWNyYWZ0OmRhcmtfb2FrX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2j2PTvdJJHcVQMKAG5ldHdvcmtfaWTwjOCeCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:mangrove_fence_gate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTrAgAACAQAbmFtZR0AbWluZWNyYWZ0Om1hbmdyb3ZlX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2i/kOhBKiI/dAMKAG5ldHdvcmtfaWSfweCSCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTrAgAACAQAbmFtZR0AbWluZWNyYWZ0Om1hbmdyb3ZlX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2i/kOhBKiI/dAMKAG5ldHdvcmtfaWSfweCSCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:cherry_fence_gate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQUAwAACAQAbmFtZRsAbWluZWNyYWZ0OmNoZXJyeV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoKWLgCk0z+PsDCgBuZXR3b3JrX2lk/9bTZQoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQUAwAACAQAbmFtZRsAbWluZWNyYWZ0OmNoZXJyeV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoKWLgCk0z+PsDCgBuZXR3b3JrX2lk/9bTZQoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:bamboo_fence_gate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAwAACAQAbmFtZRsAbWluZWNyYWZ0OmJhbWJvb19mZW5jZV9nYXRlBAkAbmFtZV9oYXNopH1JrUgwdIADCgBuZXR3b3JrX2lkzIpPywoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAwAACAQAbmFtZRsAbWluZWNyYWZ0OmJhbWJvb19mZW5jZV9nYXRlBAkAbmFtZV9oYXNopH1JrUgwdIADCgBuZXR3b3JrX2lkzIpPywoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:crimson_fence_gate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAgAACAQAbmFtZRwAbWluZWNyYWZ0OmNyaW1zb25fZmVuY2VfZ2F0ZQQJAG5hbWVfaGFzaHE3Gfd0Z2d2AwoAbmV0d29ya19pZDQzVbEKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQsAaW5fd2FsbF9iaXQAAQgAb3Blbl9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAgAACAQAbmFtZRwAbWluZWNyYWZ0OmNyaW1zb25fZmVuY2VfZ2F0ZQQJAG5hbWVfaGFzaHE3Gfd0Z2d2AwoAbmV0d29ya19pZDQzVbEKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQsAaW5fd2FsbF9iaXQAAQgAb3Blbl9iaXQAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:warped_fence_gate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAgAACAQAbmFtZRsAbWluZWNyYWZ0OndhcnBlZF9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoy0oIBjDIG4kDCgBuZXR3b3JrX2lkkf+/3QoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAgAACAQAbmFtZRsAbWluZWNyYWZ0OndhcnBlZF9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoy0oIBjDIG4kDCgBuZXR3b3JrX2lkkf+/3QoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:normal_stone_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAQAACAQAbmFtZR0AbWluZWNyYWZ0Om5vcm1hbF9zdG9uZV9zdGFpcnMECQBuYW1lX2hhc2hAEktZZOkGIwMKAG5ldHdvcmtfaWQeH1ALCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAQAACAQAbmFtZR0AbWluZWNyYWZ0Om5vcm1hbF9zdG9uZV9zdGFpcnMECQBuYW1lX2hhc2hAEktZZOkGIwMKAG5ldHdvcmtfaWQeH1ALCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:stone_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRDAAAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX3N0YWlycwQJAG5hbWVfaGFzaNRjqVC5GRVDAwoAbmV0d29ya19pZDcCv+MKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRDAAAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX3N0YWlycwQJAG5hbWVfaGFzaNRjqVC5GRVDAwoAbmV0d29ya19pZDcCv+MKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:mossy_cobblestone_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSyAQAACAQAbmFtZSIAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lX3N0YWlycwQJAG5hbWVfaGFzaMVSTq5z9n1RAwoAbmV0d29ya19pZFIfrhkKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSyAQAACAQAbmFtZSIAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lX3N0YWlycwQJAG5hbWVfaGFzaMVSTq5z9n1RAwoAbmV0d29ya19pZFIfrhkKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:oak_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ1AAAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19zdGFpcnMECQBuYW1lX2hhc2jk/HFzdXy0FQMKAG5ldHdvcmtfaWQJjyzBCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ1AAAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19zdGFpcnMECQBuYW1lX2hhc2jk/HFzdXy0FQMKAG5ldHdvcmtfaWQJjyzBCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:spruce_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSGAAAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9zdGFpcnMECQBuYW1lX2hhc2iznygw7uBPBQMKAG5ldHdvcmtfaWTv+is3CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSGAAAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9zdGFpcnMECQBuYW1lX2hhc2iznygw7uBPBQMKAG5ldHdvcmtfaWTv+is3CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:birch_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSHAAAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX3N0YWlycwQJAG5hbWVfaGFzaPfhbL619a3GAwoAbmV0d29ya19pZFyPlHAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSHAAAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX3N0YWlycwQJAG5hbWVfaGFzaPfhbL619a3GAwoAbmV0d29ya19pZFyPlHAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:jungle_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSIAAAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9zdGFpcnMECQBuYW1lX2hhc2jodJsHUbOVxQMKAG5ldHdvcmtfaWR0z5d4CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSIAAAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9zdGFpcnMECQBuYW1lX2hhc2jodJsHUbOVxQMKAG5ldHdvcmtfaWR0z5d4CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:acacia_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSjAAAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9zdGFpcnMECQBuYW1lX2hhc2h3x1NmD43IqQMKAG5ldHdvcmtfaWS7Jwz6CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSjAAAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9zdGFpcnMECQBuYW1lX2hhc2h3x1NmD43IqQMKAG5ldHdvcmtfaWS7Jwz6CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:dark_oak_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAAAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX3N0YWlycwQJAG5hbWVfaGFzaMfwkbYPbNmAAwoAbmV0d29ya19pZCmBYKAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAAAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX3N0YWlycwQJAG5hbWVfaGFzaMfwkbYPbNmAAwoAbmV0d29ya19pZCmBYKAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:mangrove_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTnAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX3N0YWlycwQJAG5hbWVfaGFzaNpUDY+uGMpyAwoAbmV0d29ya19pZChzUAsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTnAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX3N0YWlycwQJAG5hbWVfaGFzaNpUDY+uGMpyAwoAbmV0d29ya19pZChzUAsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:cherry_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQcAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9zdGFpcnMECQBuYW1lX2hhc2jMtr0v9JY4zwMKAG5ldHdvcmtfaWRQwq31CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQcAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9zdGFpcnMECQBuYW1lX2hhc2jMtr0v9JY4zwMKAG5ldHdvcmtfaWRQwq31CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:bamboo_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWT/AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19zdGFpcnMECQBuYW1lX2hhc2jFOzWL8PalKwMKAG5ldHdvcmtfaWTVPh42CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWT/AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19zdGFpcnMECQBuYW1lX2hhc2jFOzWL8PalKwMKAG5ldHdvcmtfaWTVPh42CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:bamboo_mosaic_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQKAwAACAQAbmFtZR4AbWluZWNyYWZ0OmJhbWJvb19tb3NhaWNfc3RhaXJzBAkAbmFtZV9oYXNoNLPiveSHPaoDCgBuZXR3b3JrX2lk44PHjgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQKAwAACAQAbmFtZR4AbWluZWNyYWZ0OmJhbWJvb19tb3NhaWNfc3RhaXJzBAkAbmFtZV9oYXNoNLPiveSHPaoDCgBuZXR3b3JrX2lk44PHjgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:stone_brick_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRtAAAACAQAbmFtZRwAbWluZWNyYWZ0OnN0b25lX2JyaWNrX3N0YWlycwQJAG5hbWVfaGFzaN6tQViRo5cwAwoAbmV0d29ya19pZDMyMgIKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRtAAAACAQAbmFtZRwAbWluZWNyYWZ0OnN0b25lX2JyaWNrX3N0YWlycwQJAG5hbWVfaGFzaN6tQViRo5cwAwoAbmV0d29ya19pZDMyMgIKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:mossy_stone_brick_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSuAQAACAQAbmFtZSIAbWluZWNyYWZ0Om1vc3N5X3N0b25lX2JyaWNrX3N0YWlycwQJAG5hbWVfaGFzaIB/Zv5YBPuYAwoAbmV0d29ya19pZANTOsMKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSuAQAACAQAbmFtZSIAbWluZWNyYWZ0Om1vc3N5X3N0b25lX2JyaWNrX3N0YWlycwQJAG5hbWVfaGFzaIB/Zv5YBPuYAwoAbmV0d29ya19pZANTOsMKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:sandstone_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSAAAAACAQAbmFtZRoAbWluZWNyYWZ0OnNhbmRzdG9uZV9zdGFpcnMECQBuYW1lX2hhc2hOyA0BoYUOPQMKAG5ldHdvcmtfaWSV/834CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSAAAAACAQAbmFtZRoAbWluZWNyYWZ0OnNhbmRzdG9uZV9zdGFpcnMECQBuYW1lX2hhc2hOyA0BoYUOPQMKAG5ldHdvcmtfaWSV/834CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:smooth_sandstone_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSwAQAACAQAbmFtZSEAbWluZWNyYWZ0OnNtb290aF9zYW5kc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNoB+CuCd8Ruz8DCgBuZXR3b3JrX2lksR+m8QoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSwAQAACAQAbmFtZSEAbWluZWNyYWZ0OnNtb290aF9zYW5kc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNoB+CuCd8Ruz8DCgBuZXR3b3JrX2lksR+m8QoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:red_sandstone_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWS0AAAACAQAbmFtZR4AbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNoPs0LpHPL24YDCgBuZXR3b3JrX2lkLYVt3woGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWS0AAAACAQAbmFtZR4AbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNoPs0LpHPL24YDCgBuZXR3b3JrX2lkLYVt3woGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:smooth_red_sandstone_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAQAACAQAbmFtZSUAbWluZWNyYWZ0OnNtb290aF9yZWRfc2FuZHN0b25lX3N0YWlycwQJAG5hbWVfaGFzaBvjtQv5pf+MAwoAbmV0d29ya19pZMHNND8KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAQAACAQAbmFtZSUAbWluZWNyYWZ0OnNtb290aF9yZWRfc2FuZHN0b25lX3N0YWlycwQJAG5hbWVfaGFzaBvjtQv5pf+MAwoAbmV0d29ya19pZMHNND8KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:granite_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAQAACAQAbmFtZRgAbWluZWNyYWZ0OmdyYW5pdGVfc3RhaXJzBAkAbmFtZV9oYXNoGzpvtoqKQjgDCgBuZXR3b3JrX2lkPkcB1goGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAQAACAQAbmFtZRgAbWluZWNyYWZ0OmdyYW5pdGVfc3RhaXJzBAkAbmFtZV9oYXNoGzpvtoqKQjgDCgBuZXR3b3JrX2lkPkcB1goGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:polished_granite_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAQAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2dyYW5pdGVfc3RhaXJzBAkAbmFtZV9oYXNo3PvbSfEQklIDCgBuZXR3b3JrX2lkMmEm3AoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAQAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2dyYW5pdGVfc3RhaXJzBAkAbmFtZV9oYXNo3PvbSfEQklIDCgBuZXR3b3JrX2lkMmEm3AoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:diorite_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAQAACAQAbmFtZRgAbWluZWNyYWZ0OmRpb3JpdGVfc3RhaXJzBAkAbmFtZV9oYXNoi73T8VQuZmcDCgBuZXR3b3JrX2lk6i6nBQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAQAACAQAbmFtZRgAbWluZWNyYWZ0OmRpb3JpdGVfc3RhaXJzBAkAbmFtZV9oYXNoi73T8VQuZmcDCgBuZXR3b3JrX2lk6i6nBQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:polished_diorite_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSsAQAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2Rpb3JpdGVfc3RhaXJzBAkAbmFtZV9oYXNoFKRJd5Wk5L0DCgBuZXR3b3JrX2lkbt2ioAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSsAQAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2Rpb3JpdGVfc3RhaXJzBAkAbmFtZV9oYXNoFKRJd5Wk5L0DCgBuZXR3b3JrX2lkbt2ioAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:andesite_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAQAACAQAbmFtZRkAbWluZWNyYWZ0OmFuZGVzaXRlX3N0YWlycwQJAG5hbWVfaGFzaO5w2FKBw76EAwoAbmV0d29ya19pZKhXEgUKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAQAACAQAbmFtZRkAbWluZWNyYWZ0OmFuZGVzaXRlX3N0YWlycwQJAG5hbWVfaGFzaO5w2FKBw76EAwoAbmV0d29ya19pZKhXEgUKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:polished_andesite_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWStAQAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2FuZGVzaXRlX3N0YWlycwQJAG5hbWVfaGFzaNcZZ/zmLInIAwoAbmV0d29ya19pZJTHrlEKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWStAQAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2FuZGVzaXRlX3N0YWlycwQJAG5hbWVfaGFzaNcZZ/zmLInIAwoAbmV0d29ya19pZJTHrlEKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:brick_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRsAAAACAQAbmFtZRYAbWluZWNyYWZ0OmJyaWNrX3N0YWlycwQJAG5hbWVfaGFzaMyt+cRDk5O2AwoAbmV0d29ya19pZNeMh58KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRsAAAACAQAbmFtZRYAbWluZWNyYWZ0OmJyaWNrX3N0YWlycwQJAG5hbWVfaGFzaMyt+cRDk5O2AwoAbmV0d29ya19pZNeMh58KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:nether_brick_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRyAAAACAQAbmFtZR0AbWluZWNyYWZ0Om5ldGhlcl9icmlja19zdGFpcnMECQBuYW1lX2hhc2jRqIoOXgifBAMKAG5ldHdvcmtfaWQDiw5yCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRyAAAACAQAbmFtZR0AbWluZWNyYWZ0Om5ldGhlcl9icmlja19zdGFpcnMECQBuYW1lX2hhc2jRqIoOXgifBAMKAG5ldHdvcmtfaWQDiw5yCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:red_nether_brick_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWS3AQAACAQAbmFtZSEAbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNogQvosSbcj7kDCgBuZXR3b3JrX2lkx2IMtAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWS3AQAACAQAbmFtZSEAbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNogQvosSbcj7kDCgBuZXR3b3JrX2lkx2IMtAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:end_brick_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSxAQAACAQAbmFtZRoAbWluZWNyYWZ0OmVuZF9icmlja19zdGFpcnMECQBuYW1lX2hhc2hmlAk+QhsUsQMKAG5ldHdvcmtfaWTN7KFaCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSxAQAACAQAbmFtZRoAbWluZWNyYWZ0OmVuZF9icmlja19zdGFpcnMECQBuYW1lX2hhc2hmlAk+QhsUsQMKAG5ldHdvcmtfaWTN7KFaCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:quartz_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWScAAAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9zdGFpcnMECQBuYW1lX2hhc2hmvpvOqGi6egMKAG5ldHdvcmtfaWRmUTh7CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWScAAAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9zdGFpcnMECQBuYW1lX2hhc2hmvpvOqGi6egMKAG5ldHdvcmtfaWRmUTh7CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:smooth_quartz_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWS4AQAACAQAbmFtZR4AbWluZWNyYWZ0OnNtb290aF9xdWFydHpfc3RhaXJzBAkAbmFtZV9oYXNoNZZ9rX0qZOsDCgBuZXR3b3JrX2lkzsgQyQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWS4AQAACAQAbmFtZR4AbWluZWNyYWZ0OnNtb290aF9xdWFydHpfc3RhaXJzBAkAbmFtZV9oYXNoNZZ9rX0qZOsDCgBuZXR3b3JrX2lkzsgQyQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:purpur_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAAAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnB1cl9zdGFpcnMECQBuYW1lX2hhc2ifwDxeezXD7gMKAG5ldHdvcmtfaWTT+rxiCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAAAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnB1cl9zdGFpcnMECQBuYW1lX2hhc2ifwDxeezXD7gMKAG5ldHdvcmtfaWTT+rxiCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:prismarine_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAQAACAQAbmFtZRsAbWluZWNyYWZ0OnByaXNtYXJpbmVfc3RhaXJzBAkAbmFtZV9oYXNooTHSZ+IrYtcDCgBuZXR3b3JrX2lkxTJfeAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAQAACAQAbmFtZRsAbWluZWNyYWZ0OnByaXNtYXJpbmVfc3RhaXJzBAkAbmFtZV9oYXNooTHSZ+IrYtcDCgBuZXR3b3JrX2lkxTJfeAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:dark_prismarine_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAQAACAQAbmFtZSAAbWluZWNyYWZ0OmRhcmtfcHJpc21hcmluZV9zdGFpcnMECQBuYW1lX2hhc2hIciLmam4o4AMKAG5ldHdvcmtfaWTVu7TCCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAQAACAQAbmFtZSAAbWluZWNyYWZ0OmRhcmtfcHJpc21hcmluZV9zdGFpcnMECQBuYW1lX2hhc2hIciLmam4o4AMKAG5ldHdvcmtfaWTVu7TCCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:prismarine_bricks_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAQAACAQAbmFtZSIAbWluZWNyYWZ0OnByaXNtYXJpbmVfYnJpY2tzX3N0YWlycwQJAG5hbWVfaGFzaNIjq1oBlZMMAwoAbmV0d29ya19pZGEFwLYKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAQAACAQAbmFtZSIAbWluZWNyYWZ0OnByaXNtYXJpbmVfYnJpY2tzX3N0YWlycwQJAG5hbWVfaGFzaNIjq1oBlZMMAwoAbmV0d29ya19pZGEFwLYKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:crimson_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWT9AQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fc3RhaXJzBAkAbmFtZV9oYXNoZJqIzCBpCq4DCgBuZXR3b3JrX2lktXE00AoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWT9AQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fc3RhaXJzBAkAbmFtZV9oYXNoZJqIzCBpCq4DCgBuZXR3b3JrX2lktXE00AoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:warped_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWT+AQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9zdGFpcnMECQBuYW1lX2hhc2hOkY27jLD4RQMKAG5ldHdvcmtfaWQ+E5VrCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWT+AQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9zdGFpcnMECQBuYW1lX2hhc2hOkY27jLD4RQMKAG5ldHdvcmtfaWQ+E5VrCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:blackstone_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAgAACAQAbmFtZRsAbWluZWNyYWZ0OmJsYWNrc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNokdoUb76p9McDCgBuZXR3b3JrX2lk5fWI5goGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAgAACAQAbmFtZRsAbWluZWNyYWZ0OmJsYWNrc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNokdoUb76p9McDCgBuZXR3b3JrX2lk5fWI5goGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:polished_blackstone_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQjAgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNolCFtFIE8MmADCgBuZXR3b3JrX2lkGTf7sgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQjAgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNolCFtFIE8MmADCgBuZXR3b3JrX2lkGTf7sgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:polished_blackstone_brick_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQSAgAACAQAbmFtZSoAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNonks6UlfpOmkDCgBuZXR3b3JrX2lkgYeOdAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQSAgAACAQAbmFtZSoAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNonks6UlfpOmkDCgBuZXR3b3JrX2lkgYeOdAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:cut_copper_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAgAACAQAbmFtZRsAbWluZWNyYWZ0OmN1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoHfoAXYq5G3MDCgBuZXR3b3JrX2lkeetf7woGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAgAACAQAbmFtZRsAbWluZWNyYWZ0OmN1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoHfoAXYq5G3MDCgBuZXR3b3JrX2lkeetf7woGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:exposed_cut_copper_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAgAACAQAbmFtZSMAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcl9zdGFpcnMECQBuYW1lX2hhc2howneQGtZ9cgMKAG5ldHdvcmtfaWSg73zdCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAgAACAQAbmFtZSMAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcl9zdGFpcnMECQBuYW1lX2hhc2howneQGtZ9cgMKAG5ldHdvcmtfaWSg73zdCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:weathered_cut_copper_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAgAACAQAbmFtZSUAbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyX3N0YWlycwQJAG5hbWVfaGFzaP+R5loXxrVgAwoAbmV0d29ya19pZOnbRf4KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAgAACAQAbmFtZSUAbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyX3N0YWlycwQJAG5hbWVfaGFzaP+R5loXxrVgAwoAbmV0d29ya19pZOnbRf4KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:oxidized_cut_copper_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRkAgAACAQAbmFtZSQAbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNo6Jeoq5rsPxsDCgBuZXR3b3JrX2lkmRjDnQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRkAgAACAQAbmFtZSQAbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNo6Jeoq5rsPxsDCgBuZXR3b3JrX2lkmRjDnQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:waxed_cut_copper_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRlAgAACAQAbmFtZSEAbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoh07CQj0/SR8DCgBuZXR3b3JrX2lkmYqoqAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRlAgAACAQAbmFtZSEAbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoh07CQj0/SR8DCgBuZXR3b3JrX2lkmYqoqAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:waxed_exposed_cut_copper_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRmAgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcl9zdGFpcnMECQBuYW1lX2hhc2guVct1ilmxTwMKAG5ldHdvcmtfaWQgCPROCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRmAgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcl9zdGFpcnMECQBuYW1lX2hhc2guVct1ilmxTwMKAG5ldHdvcmtfaWQgCPROCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:waxed_weathered_cut_copper_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRnAgAACAQAbmFtZSsAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyX3N0YWlycwQJAG5hbWVfaGFzaPXC8Sz/phCpAwoAbmV0d29ya19pZHlwHVsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRnAgAACAQAbmFtZSsAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyX3N0YWlycwQJAG5hbWVfaGFzaPXC8Sz/phCpAwoAbmV0d29ya19pZHlwHVsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:waxed_oxidized_cut_copper_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWS/AgAACAQAbmFtZSoAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoaqGdkuhxVZUDCgBuZXR3b3JrX2lkYQXzzgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWS/AgAACAQAbmFtZSoAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoaqGdkuhxVZUDCgBuZXR3b3JrX2lkYQXzzgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:cobbled_deepslate_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR8AgAACAQAbmFtZSIAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3N0YWlycwQJAG5hbWVfaGFzaPIfa+TpyJcIAwoAbmV0d29ya19pZJUvOYIKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR8AgAACAQAbmFtZSIAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3N0YWlycwQJAG5hbWVfaGFzaPIfa+TpyJcIAwoAbmV0d29ya19pZJUvOYIKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:deepslate_tile_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3N0YWlycwQJAG5hbWVfaGFzaGFRFzB72mN2AwoAbmV0d29ya19pZJEOgIsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3N0YWlycwQJAG5hbWVfaGFzaGFRFzB72mN2AwoAbmV0d29ya19pZJEOgIsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:polished_deepslate_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSAAgAACAQAbmFtZSMAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV9zdGFpcnMECQBuYW1lX2hhc2iNCYxVik9sGAMKAG5ldHdvcmtfaWSRVPnYCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSAAgAACAQAbmFtZSMAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV9zdGFpcnMECQBuYW1lX2hhc2iNCYxVik9sGAMKAG5ldHdvcmtfaWSRVPnYCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:deepslate_brick_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSIAgAACAQAbmFtZSAAbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja19zdGFpcnMECQBuYW1lX2hhc2hIasOahEf83wMKAG5ldHdvcmtfaWQ1qEDCCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSIAgAACAQAbmFtZSAAbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja19zdGFpcnMECQBuYW1lX2hhc2hIasOahEf83wMKAG5ldHdvcmtfaWQ1qEDCCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:mud_brick_stairs", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAgAACAQAbmFtZRoAbWluZWNyYWZ0Om11ZF9icmlja19zdGFpcnMECQBuYW1lX2hhc2gt3qxK1NWajAMKAG5ldHdvcmtfaWSm9N3MCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAgAACAQAbmFtZRoAbWluZWNyYWZ0Om11ZF9icmlja19zdGFpcnMECQBuYW1lX2hhc2gt3qxK1NWajAMKAG5ldHdvcmtfaWSm9N3MCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:wooden_door" @@ -478,1575 +478,1727 @@ }, { "id": "minecraft:trapdoor", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRgAAAACAQAbmFtZRIAbWluZWNyYWZ0OnRyYXBkb29yBAkAbmFtZV9oYXNotYiAJGtN0xADCgBuZXR3b3JrX2lkyTAWkAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRgAAAACAQAbmFtZRIAbWluZWNyYWZ0OnRyYXBkb29yBAkAbmFtZV9oYXNotYiAJGtN0xADCgBuZXR3b3JrX2lkyTAWkAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:spruce_trapdoor", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSUAQAACAQAbmFtZRkAbWluZWNyYWZ0OnNwcnVjZV90cmFwZG9vcgQJAG5hbWVfaGFzaOwlfbgBkUW4AwoAbmV0d29ya19pZPHy1K0KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSUAQAACAQAbmFtZRkAbWluZWNyYWZ0OnNwcnVjZV90cmFwZG9vcgQJAG5hbWVfaGFzaOwlfbgBkUW4AwoAbmV0d29ya19pZPHy1K0KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:birch_trapdoor", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAQAACAQAbmFtZRgAbWluZWNyYWZ0OmJpcmNoX3RyYXBkb29yBAkAbmFtZV9oYXNoSLtLweOLJ7wDCgBuZXR3b3JrX2lkeJWDfgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAQAACAQAbmFtZRgAbWluZWNyYWZ0OmJpcmNoX3RyYXBkb29yBAkAbmFtZV9oYXNoSLtLweOLJ7wDCgBuZXR3b3JrX2lkeJWDfgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:jungle_trapdoor", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSTAQAACAQAbmFtZRkAbWluZWNyYWZ0Omp1bmdsZV90cmFwZG9vcgQJAG5hbWVfaGFzaDP/TnM9wyCIAwoAbmV0d29ya19pZEy2fJoKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSTAQAACAQAbmFtZRkAbWluZWNyYWZ0Omp1bmdsZV90cmFwZG9vcgQJAG5hbWVfaGFzaDP/TnM9wyCIAwoAbmV0d29ya19pZEy2fJoKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:acacia_trapdoor", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSQAQAACAQAbmFtZRkAbWluZWNyYWZ0OmFjYWNpYV90cmFwZG9vcgQJAG5hbWVfaGFzaMj8xi3vmEKOAwoAbmV0d29ya19pZOHj8E8KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSQAQAACAQAbmFtZRkAbWluZWNyYWZ0OmFjYWNpYV90cmFwZG9vcgQJAG5hbWVfaGFzaMj8xi3vmEKOAwoAbmV0d29ya19pZOHj8E8KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:dark_oak_trapdoor", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSSAQAACAQAbmFtZRsAbWluZWNyYWZ0OmRhcmtfb2FrX3RyYXBkb29yBAkAbmFtZV9oYXNomB2GGJQ2aOMDCgBuZXR3b3JrX2lko5ZHTwoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSSAQAACAQAbmFtZRsAbWluZWNyYWZ0OmRhcmtfb2FrX3RyYXBkb29yBAkAbmFtZV9oYXNomB2GGJQ2aOMDCgBuZXR3b3JrX2lko5ZHTwoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:mangrove_trapdoor", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTvAgAACAQAbmFtZRsAbWluZWNyYWZ0Om1hbmdyb3ZlX3RyYXBkb29yBAkAbmFtZV9oYXNooV3kQsQUUmkDCgBuZXR3b3JrX2lkkF/mxAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTvAgAACAQAbmFtZRsAbWluZWNyYWZ0Om1hbmdyb3ZlX3RyYXBkb29yBAkAbmFtZV9oYXNooV3kQsQUUmkDCgBuZXR3b3JrX2lkkF/mxAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:cherry_trapdoor", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQeAwAACAQAbmFtZRkAbWluZWNyYWZ0OmNoZXJyeV90cmFwZG9vcgQJAG5hbWVfaGFzaH/PefpfdHgtAwoAbmV0d29ya19pZOA7eNgKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQeAwAACAQAbmFtZRkAbWluZWNyYWZ0OmNoZXJyeV90cmFwZG9vcgQJAG5hbWVfaGFzaH/PefpfdHgtAwoAbmV0d29ya19pZOA7eNgKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:bamboo_trapdoor", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAwAACAQAbmFtZRkAbWluZWNyYWZ0OmJhbWJvb190cmFwZG9vcgQJAG5hbWVfaGFzaJrEOpsTwtKCAwoAbmV0d29ya19pZLvbPz8KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAwAACAQAbmFtZRkAbWluZWNyYWZ0OmJhbWJvb190cmFwZG9vcgQJAG5hbWVfaGFzaJrEOpsTwtKCAwoAbmV0d29ya19pZLvbPz8KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:iron_trapdoor", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSnAAAACAQAbmFtZRcAbWluZWNyYWZ0Omlyb25fdHJhcGRvb3IECQBuYW1lX2hhc2gwA+IumsEiGQMKAG5ldHdvcmtfaWTvSVl/CgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSnAAAACAQAbmFtZRcAbWluZWNyYWZ0Omlyb25fdHJhcGRvb3IECQBuYW1lX2hhc2gwA+IumsEiGQMKAG5ldHdvcmtfaWTvSVl/CgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:crimson_trapdoor", - "block_state_b64": "CgAAAwgAYmxvY2tfaWT1AQAACAQAbmFtZRoAbWluZWNyYWZ0OmNyaW1zb25fdHJhcGRvb3IECQBuYW1lX2hhc2jHXufTnwUkYgMKAG5ldHdvcmtfaWQLjMYVCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWT1AQAACAQAbmFtZRoAbWluZWNyYWZ0OmNyaW1zb25fdHJhcGRvb3IECQBuYW1lX2hhc2jHXufTnwUkYgMKAG5ldHdvcmtfaWQLjMYVCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:warped_trapdoor", - "block_state_b64": "CgAAAwgAYmxvY2tfaWT2AQAACAQAbmFtZRkAbWluZWNyYWZ0OndhcnBlZF90cmFwZG9vcgQJAG5hbWVfaGFzaA20wG/+vkd6AwoAbmV0d29ya19pZHKR/hYKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWT2AQAACAQAbmFtZRkAbWluZWNyYWZ0OndhcnBlZF90cmFwZG9vcgQJAG5hbWVfaGFzaA20wG/+vkd6AwoAbmV0d29ya19pZHKR/hYKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:iron_bars", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRlAAAACAQAbmFtZRMAbWluZWNyYWZ0Omlyb25fYmFycwQJAG5hbWVfaGFzaPuefWSNAe56AwoAbmV0d29ya19pZN2LB5IKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRlAAAACAQAbmFtZRMAbWluZWNyYWZ0Omlyb25fYmFycwQJAG5hbWVfaGFzaPuefWSNAe56AwoAbmV0d29ya19pZN2LB5IKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:glass", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQUAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmdsYXNzBAkAbmFtZV9oYXNowGJByfWff6gDCgBuZXR3b3JrX2lk0hdLNwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQUAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmdsYXNzBAkAbmFtZV9oYXNowGJByfWff6gDCgBuZXR3b3JrX2lk0hdLNwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:white_stained_glass", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTxAAAACAQAbmFtZR0AbWluZWNyYWZ0OndoaXRlX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2iHubqoMbu9fAMKAG5ldHdvcmtfaWRndBrUCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTxAAAACAQAbmFtZR0AbWluZWNyYWZ0OndoaXRlX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2iHubqoMbu9fAMKAG5ldHdvcmtfaWRndBrUCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:light_gray_stained_glass", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSnAwAACAQAbmFtZSIAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaKKa+LrRsHQhAwoAbmV0d29ya19pZEv2giYKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSnAwAACAQAbmFtZSIAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaKKa+LrRsHQhAwoAbmV0d29ya19pZEv2giYKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:gray_stained_glass", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSmAwAACAQAbmFtZRwAbWluZWNyYWZ0OmdyYXlfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaIETy7Y/HZREAwoAbmV0d29ya19pZDomVrUKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSmAwAACAQAbmFtZRwAbWluZWNyYWZ0OmdyYXlfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaIETy7Y/HZREAwoAbmV0d29ya19pZDomVrUKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:black_stained_glass", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSuAwAACAQAbmFtZR0AbWluZWNyYWZ0OmJsYWNrX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2iV6BCwpfDMmwMKAG5ldHdvcmtfaWSV7doJCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSuAwAACAQAbmFtZR0AbWluZWNyYWZ0OmJsYWNrX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2iV6BCwpfDMmwMKAG5ldHdvcmtfaWSV7doJCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:brown_stained_glass", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAwAACAQAbmFtZR0AbWluZWNyYWZ0OmJyb3duX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2igsEiq5np8JgMKAG5ldHdvcmtfaWRMzE/lCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAwAACAQAbmFtZR0AbWluZWNyYWZ0OmJyb3duX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2igsEiq5np8JgMKAG5ldHdvcmtfaWRMzE/lCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:red_stained_glass", - "block_state_b64": "CgAAAwgAYmxvY2tfaWStAwAACAQAbmFtZRsAbWluZWNyYWZ0OnJlZF9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNoCa2J12/lQoIDCgBuZXR3b3JrX2lk283lWAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWStAwAACAQAbmFtZRsAbWluZWNyYWZ0OnJlZF9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNoCa2J12/lQoIDCgBuZXR3b3JrX2lk283lWAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:orange_stained_glass", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSgAwAACAQAbmFtZR4AbWluZWNyYWZ0Om9yYW5nZV9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNozgjAuvzhxGsDCgBuZXR3b3JrX2lkW5CkhQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSgAwAACAQAbmFtZR4AbWluZWNyYWZ0Om9yYW5nZV9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNozgjAuvzhxGsDCgBuZXR3b3JrX2lkW5CkhQoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:yellow_stained_glass", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSjAwAACAQAbmFtZR4AbWluZWNyYWZ0OnllbGxvd19zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNo7EbHMd5WVugDCgBuZXR3b3JrX2lkkdDyXQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSjAwAACAQAbmFtZR4AbWluZWNyYWZ0OnllbGxvd19zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNo7EbHMd5WVugDCgBuZXR3b3JrX2lkkdDyXQoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:lime_stained_glass", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAwAACAQAbmFtZRwAbWluZWNyYWZ0OmxpbWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaBtZA1nZtwcFAwoAbmV0d29ya19pZDxX85UKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAwAACAQAbmFtZRwAbWluZWNyYWZ0OmxpbWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaBtZA1nZtwcFAwoAbmV0d29ya19pZDxX85UKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:green_stained_glass", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSsAwAACAQAbmFtZR0AbWluZWNyYWZ0OmdyZWVuX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2h91ptDgbehWwMKAG5ldHdvcmtfaWTlDhnECgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSsAwAACAQAbmFtZR0AbWluZWNyYWZ0OmdyZWVuX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2h91ptDgbehWwMKAG5ldHdvcmtfaWTlDhnECgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:cyan_stained_glass", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAwAACAQAbmFtZRwAbWluZWNyYWZ0OmN5YW5fc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaBkIYQ8nQLqbAwoAbmV0d29ya19pZOL1lHsKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAwAACAQAbmFtZRwAbWluZWNyYWZ0OmN5YW5fc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaBkIYQ8nQLqbAwoAbmV0d29ya19pZOL1lHsKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:light_blue_stained_glass", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAwAACAQAbmFtZSIAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaLt05n1G0fiSAwoAbmV0d29ya19pZNbwulIKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAwAACAQAbmFtZSIAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaLt05n1G0fiSAwoAbmV0d29ya19pZNbwulIKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:blue_stained_glass", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAwAACAQAbmFtZRwAbWluZWNyYWZ0OmJsdWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaPhLocSfzduRAwoAbmV0d29ya19pZENsjFwKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAwAACAQAbmFtZRwAbWluZWNyYWZ0OmJsdWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaPhLocSfzduRAwoAbmV0d29ya19pZENsjFwKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:purple_stained_glass", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAwAACAQAbmFtZR4AbWluZWNyYWZ0OnB1cnBsZV9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNoJk0DhRO0szUDCgBuZXR3b3JrX2lkD98ZxgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAwAACAQAbmFtZR4AbWluZWNyYWZ0OnB1cnBsZV9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNoJk0DhRO0szUDCgBuZXR3b3JrX2lkD98ZxgoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:magenta_stained_glass", - "block_state_b64": "CgAAAwgAYmxvY2tfaWShAwAACAQAbmFtZR8AbWluZWNyYWZ0Om1hZ2VudGFfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaFEDeFiJj3zSAwoAbmV0d29ya19pZG+iFRoKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAwAACAQAbmFtZR8AbWluZWNyYWZ0Om1hZ2VudGFfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaFEDeFiJj3zSAwoAbmV0d29ya19pZG+iFRoKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:pink_stained_glass", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAwAACAQAbmFtZRwAbWluZWNyYWZ0OnBpbmtfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaDijTX87ywxhAwoAbmV0d29ya19pZKdEricKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAwAACAQAbmFtZRwAbWluZWNyYWZ0OnBpbmtfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaDijTX87ywxhAwoAbmV0d29ya19pZKdEricKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:tinted_glass", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRNAgAACAQAbmFtZRYAbWluZWNyYWZ0OnRpbnRlZF9nbGFzcwQJAG5hbWVfaGFzaAFZWSamk6KdAwoAbmV0d29ya19pZGSvWX8KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRNAgAACAQAbmFtZRYAbWluZWNyYWZ0OnRpbnRlZF9nbGFzcwQJAG5hbWVfaGFzaAFZWSamk6KdAwoAbmV0d29ya19pZGSvWX8KBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:glass_pane", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRmAAAACAQAbmFtZRQAbWluZWNyYWZ0OmdsYXNzX3BhbmUECQBuYW1lX2hhc2gRSBHwNMQ4gQMKAG5ldHdvcmtfaWRGwixuCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRmAAAACAQAbmFtZRQAbWluZWNyYWZ0OmdsYXNzX3BhbmUECQBuYW1lX2hhc2gRSBHwNMQ4gQMKAG5ldHdvcmtfaWRGwixuCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:white_stained_glass_pane", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSgAAAACAQAbmFtZSIAbWluZWNyYWZ0OndoaXRlX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaHgxQmgJVtRrAwoAbmV0d29ya19pZBEr/DYKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSgAAAACAQAbmFtZSIAbWluZWNyYWZ0OndoaXRlX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaHgxQmgJVtRrAwoAbmV0d29ya19pZBEr/DYKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:light_gray_stained_glass_pane", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSJAwAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNon0aQw9lNkSEDCgBuZXR3b3JrX2lk9dp5VgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSJAwAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNon0aQw9lNkSEDCgBuZXR3b3JrX2lk9dp5VgoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:gray_stained_glass_pane", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSIAwAACAQAbmFtZSEAbWluZWNyYWZ0OmdyYXlfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNors74IIw+2MMDCgBuZXR3b3JrX2lkmrGO5woGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSIAwAACAQAbmFtZSEAbWluZWNyYWZ0OmdyYXlfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNors74IIw+2MMDCgBuZXR3b3JrX2lkmrGO5woGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:black_stained_glass_pane", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSQAwAACAQAbmFtZSIAbWluZWNyYWZ0OmJsYWNrX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaOK/5ZRRd+M1AwoAbmV0d29ya19pZDv++oQKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSQAwAACAQAbmFtZSIAbWluZWNyYWZ0OmJsYWNrX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaOK/5ZRRd+M1AwoAbmV0d29ya19pZDv++oQKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:brown_stained_glass_pane", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSNAwAACAQAbmFtZSIAbWluZWNyYWZ0OmJyb3duX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLHeGJyRFTIWAwoAbmV0d29ya19pZMz9L0wKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSNAwAACAQAbmFtZSIAbWluZWNyYWZ0OmJyb3duX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLHeGJyRFTIWAwoAbmV0d29ya19pZMz9L0wKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:red_stained_glass_pane", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAwAACAQAbmFtZSAAbWluZWNyYWZ0OnJlZF9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2gGr4x6JheAywMKAG5ldHdvcmtfaWQBjCTmCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAwAACAQAbmFtZSAAbWluZWNyYWZ0OnJlZF9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2gGr4x6JheAywMKAG5ldHdvcmtfaWQBjCTmCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:orange_stained_glass_pane", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAwAACAQAbmFtZSMAbWluZWNyYWZ0Om9yYW5nZV9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2hbHxPD2gEbEAMKAG5ldHdvcmtfaWSt/7a5CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAwAACAQAbmFtZSMAbWluZWNyYWZ0Om9yYW5nZV9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2hbHxPD2gEbEAMKAG5ldHdvcmtfaWSt/7a5CgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:yellow_stained_glass_pane", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAwAACAQAbmFtZSMAbWluZWNyYWZ0OnllbGxvd19zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2g9tl4aOCyZBwMKAG5ldHdvcmtfaWTXRAS7CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAwAACAQAbmFtZSMAbWluZWNyYWZ0OnllbGxvd19zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2g9tl4aOCyZBwMKAG5ldHdvcmtfaWTXRAS7CgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:lime_stained_glass_pane", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSGAwAACAQAbmFtZSEAbWluZWNyYWZ0OmxpbWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNo3CtUyLwoGegDCgBuZXR3b3JrX2lkYJDnggoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSGAwAACAQAbmFtZSEAbWluZWNyYWZ0OmxpbWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNo3CtUyLwoGegDCgBuZXR3b3JrX2lkYJDnggoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:green_stained_glass_pane", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSOAwAACAQAbmFtZSIAbWluZWNyYWZ0OmdyZWVuX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaJo6YP7IMy9SAwoAbmV0d29ya19pZHOnixoKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSOAwAACAQAbmFtZSIAbWluZWNyYWZ0OmdyZWVuX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaJo6YP7IMy9SAwoAbmV0d29ya19pZHOnixoKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:cyan_stained_glass_pane", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAwAACAQAbmFtZSEAbWluZWNyYWZ0OmN5YW5fc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoti97c6QrbLQDCgBuZXR3b3JrX2lkUqFUeQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAwAACAQAbmFtZSEAbWluZWNyYWZ0OmN5YW5fc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoti97c6QrbLQDCgBuZXR3b3JrX2lkUqFUeQoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:light_blue_stained_glass_pane", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAwAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNovDg/gQle104DCgBuZXR3b3JrX2lkFuy4MQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAwAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNovDg/gQle104DCgBuZXR3b3JrX2lkFuy4MQoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:blue_stained_glass_pane", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSMAwAACAQAbmFtZSEAbWluZWNyYWZ0OmJsdWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoGc57tiexbQMDCgBuZXR3b3JrX2lk1eBLUAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSMAwAACAQAbmFtZSEAbWluZWNyYWZ0OmJsdWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoGc57tiexbQMDCgBuZXR3b3JrX2lk1eBLUAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:purple_stained_glass_pane", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAwAACAQAbmFtZSMAbWluZWNyYWZ0OnB1cnBsZV9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2hDJHYdd0FdfQMKAG5ldHdvcmtfaWSNsdK5CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAwAACAQAbmFtZSMAbWluZWNyYWZ0OnB1cnBsZV9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2hDJHYdd0FdfQMKAG5ldHdvcmtfaWSNsdK5CgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:magenta_stained_glass_pane", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAwAACAQAbmFtZSQAbWluZWNyYWZ0Om1hZ2VudGFfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNo3pcOw5bs5XoDCgBuZXR3b3JrX2lkVbOR7AoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAwAACAQAbmFtZSQAbWluZWNyYWZ0Om1hZ2VudGFfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNo3pcOw5bs5XoDCgBuZXR3b3JrX2lkVbOR7AoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:pink_stained_glass_pane", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSHAwAACAQAbmFtZSEAbWluZWNyYWZ0OnBpbmtfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoWRhSACMWgswDCgBuZXR3b3JrX2lkIR92xwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSHAwAACAQAbmFtZSEAbWluZWNyYWZ0OnBpbmtfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoWRhSACMWgswDCgBuZXR3b3JrX2lkIR92xwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:ladder", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRBAAAACAQAbmFtZRAAbWluZWNyYWZ0OmxhZGRlcgQJAG5hbWVfaGFzaKBhqheJVOz+AwoAbmV0d29ya19pZCgvzlsKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRBAAAACAQAbmFtZRAAbWluZWNyYWZ0OmxhZGRlcgQJAG5hbWVfaGFzaKBhqheJVOz+AwoAbmV0d29ya19pZCgvzlsKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:scaffolding", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAQAACAQAbmFtZRUAbWluZWNyYWZ0OnNjYWZmb2xkaW5nBAkAbmFtZV9oYXNoYrkevrqcljwDCgBuZXR3b3JrX2lkD13mlAoGAHN0YXRlcwMJAHN0YWJpbGl0eQAAAAABDwBzdGFiaWxpdHlfY2hlY2sAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAQAACAQAbmFtZRUAbWluZWNyYWZ0OnNjYWZmb2xkaW5nBAkAbmFtZV9oYXNoYrkevrqcljwDCgBuZXR3b3JrX2lkD13mlAoGAHN0YXRlcwMJAHN0YWJpbGl0eQAAAAABDwBzdGFiaWxpdHlfY2hlY2sAAAMHAHZlcnNpb24DABUBAA==" }, { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWTkNl0JCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQwAc21vb3RoX3N0b25lAAMHAHZlcnNpb24ERhQBAA==" + "id": "minecraft:smooth_stone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRsAbWluZWNyYWZ0OnNtb290aF9zdG9uZV9zbGFiBAkAbmFtZV9oYXNon5I1yVw74uMDCgBuZXR3b3JrX2lkqvjcBQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:stone_block_slab4", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkQJoxlgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNAUAc3RvbmUAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkQJoxlgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNAUAc3RvbmUAAwcAdmVyc2lvbgMAFQEA" }, { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWRHh04KCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQsAY29iYmxlc3RvbmUAAwcAdmVyc2lvbgRGFAEA" + "id": "minecraft:cobblestone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRoBAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3NsYWIECQBuYW1lX2hhc2h5CXtW7vlQVgMKAG5ldHdvcmtfaWRDGyj2CgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkVRZB+woGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhEAbW9zc3lfY29iYmxlc3RvbmUAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkVRZB+woGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhEAbW9zc3lfY29iYmxlc3RvbmUAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:oak_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAAAACAQAbmFtZRIAbWluZWNyYWZ0Om9ha19zbGFiBAkAbmFtZV9oYXNoJp1Cp1M4jlwDCgBuZXR3b3JrX2lkZH6+owoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAAAACAQAbmFtZRIAbWluZWNyYWZ0Om9ha19zbGFiBAkAbmFtZV9oYXNoJp1Cp1M4jlwDCgBuZXR3b3JrX2lkZH6+owoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:spruce_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQjBAAACAQAbmFtZRUAbWluZWNyYWZ0OnNwcnVjZV9zbGFiBAkAbmFtZV9oYXNodQi70jB238cDCgBuZXR3b3JrX2lkrriOYQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQjBAAACAQAbmFtZRUAbWluZWNyYWZ0OnNwcnVjZV9zbGFiBAkAbmFtZV9oYXNodQi70jB238cDCgBuZXR3b3JrX2lkrriOYQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:birch_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQkBAAACAQAbmFtZRQAbWluZWNyYWZ0OmJpcmNoX3NsYWIECQBuYW1lX2hhc2gZPpfMxoOsTAMKAG5ldHdvcmtfaWThR9jyCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQkBAAACAQAbmFtZRQAbWluZWNyYWZ0OmJpcmNoX3NsYWIECQBuYW1lX2hhc2gZPpfMxoOsTAMKAG5ldHdvcmtfaWThR9jyCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:jungle_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQlBAAACAQAbmFtZRUAbWluZWNyYWZ0Omp1bmdsZV9zbGFiBAkAbmFtZV9oYXNo6gLs79NXak4DCgBuZXR3b3JrX2lk5ZiKgwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQlBAAACAQAbmFtZRUAbWluZWNyYWZ0Omp1bmdsZV9zbGFiBAkAbmFtZV9oYXNo6gLs79NXak4DCgBuZXR3b3JrX2lk5ZiKgwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:acacia_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQmBAAACAQAbmFtZRUAbWluZWNyYWZ0OmFjYWNpYV9zbGFiBAkAbmFtZV9oYXNomSdFmDnv4OUDCgBuZXR3b3JrX2lkHttaXAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmBAAACAQAbmFtZRUAbWluZWNyYWZ0OmFjYWNpYV9zbGFiBAkAbmFtZV9oYXNomSdFmDnv4OUDCgBuZXR3b3JrX2lkHttaXAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:dark_oak_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQnBAAACAQAbmFtZRcAbWluZWNyYWZ0OmRhcmtfb2FrX3NsYWIECQBuYW1lX2hhc2hJjTohRFyhIQMKAG5ldHdvcmtfaWRMzDTyCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQnBAAACAQAbmFtZRcAbWluZWNyYWZ0OmRhcmtfb2FrX3NsYWIECQBuYW1lX2hhc2hJjTohRFyhIQMKAG5ldHdvcmtfaWRMzDTyCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:mangrove_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWToAgAACAQAbmFtZRcAbWluZWNyYWZ0Om1hbmdyb3ZlX3NsYWIECQBuYW1lX2hhc2jYCcmhJPeNMwMKAG5ldHdvcmtfaWQx6U1yCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWToAgAACAQAbmFtZRcAbWluZWNyYWZ0Om1hbmdyb3ZlX3NsYWIECQBuYW1lX2hhc2jYCcmhJPeNMwMKAG5ldHdvcmtfaWQx6U1yCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:cherry_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQaAwAACAQAbmFtZRUAbWluZWNyYWZ0OmNoZXJyeV9zbGFiBAkAbmFtZV9oYXNoTt0MmVn/mqoDCgBuZXR3b3JrX2lk2VVsZQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQaAwAACAQAbmFtZRUAbWluZWNyYWZ0OmNoZXJyeV9zbGFiBAkAbmFtZV9oYXNoTt0MmVn/mqoDCgBuZXR3b3JrX2lk2VVsZQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:bamboo_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQAAwAACAQAbmFtZRUAbWluZWNyYWZ0OmJhbWJvb19zbGFiBAkAbmFtZV9oYXNoo1xuFqINeLYDCgBuZXR3b3JrX2lkVC+0twoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQAAwAACAQAbmFtZRUAbWluZWNyYWZ0OmJhbWJvb19zbGFiBAkAbmFtZV9oYXNoo1xuFqINeLYDCgBuZXR3b3JrX2lkVC+0twoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:bamboo_mosaic_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQLAwAACAQAbmFtZRwAbWluZWNyYWZ0OmJhbWJvb19tb3NhaWNfc2xhYgQJAG5hbWVfaGFzaNbVRBZ/ChI3AwoAbmV0d29ya19pZOLZHFMKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQLAwAACAQAbmFtZRwAbWluZWNyYWZ0OmJhbWJvb19tb3NhaWNfc2xhYgQJAG5hbWVfaGFzaNbVRBZ/ChI3AwoAbmV0d29ya19pZOLZHFMKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DABUBAA==" }, { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWQSiInOCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQsAc3RvbmVfYnJpY2sAAwcAdmVyc2lvbgRGFAEA" + "id": "minecraft:stone_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRqBAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2JyaWNrX3NsYWIECQBuYW1lX2hhc2js6EexuKuzrQMKAG5ldHdvcmtfaWRSsMxaCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:stone_block_slab4", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkoF89tgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNBEAbW9zc3lfc3RvbmVfYnJpY2sAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkoF89tgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNBEAbW9zc3lfc3RvbmVfYnJpY2sAAwcAdmVyc2lvbgMAFQEA" }, { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWSkoAE4CgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQkAc2FuZHN0b25lAAMHAHZlcnNpb24ERhQBAA==" + "id": "minecraft:sandstone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRnBAAACAQAbmFtZRgAbWluZWNyYWZ0OnNhbmRzdG9uZV9zbGFiBAkAbmFtZV9oYXNo/GMI0MZnrhsDCgBuZXR3b3JrX2lkFP8WmwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:stone_block_slab4", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkWfF7pgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNA0AY3V0X3NhbmRzdG9uZQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkWfF7pgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNA0AY3V0X3NhbmRzdG9uZQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkbKRChAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAc21vb3RoX3NhbmRzdG9uZQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkbKRChAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAc21vb3RoX3NhbmRzdG9uZQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkBlrvqAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMg0AcmVkX3NhbmRzdG9uZQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkBlrvqAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMg0AcmVkX3NhbmRzdG9uZQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:stone_block_slab4", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkRWFXuwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNBEAY3V0X3JlZF9zYW5kc3RvbmUAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkRWFXuwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNBEAY3V0X3JlZF9zYW5kc3RvbmUAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkom8neQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxQAc21vb3RoX3JlZF9zYW5kc3RvbmUAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkom8neQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxQAc21vb3RoX3JlZF9zYW5kc3RvbmUAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkd1ZaWgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwcAZ3Jhbml0ZQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkd1ZaWgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwcAZ3Jhbml0ZQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkISH4iwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxAAcG9saXNoZWRfZ3Jhbml0ZQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkISH4iwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxAAcG9saXNoZWRfZ3Jhbml0ZQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkqxEDMwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwcAZGlvcml0ZQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkqxEDMwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwcAZGlvcml0ZQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkSYs86QoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxAAcG9saXNoZWRfZGlvcml0ZQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkSYs86QoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxAAcG9saXNoZWRfZGlvcml0ZQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkq6BU6goGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwgAYW5kZXNpdGUAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkq6BU6goGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMwgAYW5kZXNpdGUAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkTSXY8AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxEAcG9saXNoZWRfYW5kZXNpdGUAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkTSXY8AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMxEAcG9saXNoZWRfYW5kZXNpdGUAAwcAdmVyc2lvbgMAFQEA" }, { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWQiYHKTCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQUAYnJpY2sAAwcAdmVyc2lvbgRGFAEA" + "id": "minecraft:brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRpBAAACAQAbmFtZRQAbWluZWNyYWZ0OmJyaWNrX3NsYWIECQBuYW1lX2hhc2hO/Da4jU2v4wMKAG5ldHdvcmtfaWRG/qphCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uAwAVAQA=" }, { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWTk/0LfCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQwAbmV0aGVyX2JyaWNrAAMHAHZlcnNpb24ERhQBAA==" + "id": "minecraft:nether_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRsBAAACAQAbmFtZRsAbWluZWNyYWZ0Om5ldGhlcl9icmlja19zbGFiBAkAbmFtZV9oYXNonymoa2zbbqMDCgBuZXR3b3JrX2lkquvR1QoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk/hXQ7AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcmVkX25ldGhlcl9icmljawADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk/hXQ7AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcmVkX25ldGhlcl9icmljawADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:stone_block_slab3", - "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkYJNxrwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMw8AZW5kX3N0b25lX2JyaWNrAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIzBAkAbmFtZV9oYXNoMw3274NQmpMDCgBuZXR3b3JrX2lkYJNxrwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMw8AZW5kX3N0b25lX2JyaWNrAAMHAHZlcnNpb24DABUBAA==" }, { - "id": "minecraft:stone_block_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIECQBuYW1lX2hhc2gAP8n+Ya6BWgMKAG5ldHdvcmtfaWRlj0/sCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQgPAHN0b25lX3NsYWJfdHlwZQYAcXVhcnR6AAMHAHZlcnNpb24ERhQBAA==" + "id": "minecraft:quartz_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRrBAAACAQAbmFtZRUAbWluZWNyYWZ0OnF1YXJ0el9zbGFiBAkAbmFtZV9oYXNo9JMj3upfsbwDCgBuZXR3b3JrX2lkn2g2VAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:stone_block_slab4", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkMae+2goGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNA0Ac21vb3RoX3F1YXJ0egADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWI0BAkAbmFtZV9oYXNoNA3274NQmpMDCgBuZXR3b3JrX2lkMae+2goGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfNA0Ac21vb3RoX3F1YXJ0egADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk+kMHGAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMgYAcHVycHVyAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk+kMHGAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMgYAcHVycHVyAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkKOSOMAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcHJpc21hcmluZV9yb3VnaAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkKOSOMAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcHJpc21hcmluZV9yb3VnaAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk8igLCQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMg8AcHJpc21hcmluZV9kYXJrAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lk8igLCQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMg8AcHJpc21hcmluZV9kYXJrAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:stone_block_slab2", - "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkSFbyEwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcHJpc21hcmluZV9icmljawADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lX2Jsb2NrX3NsYWIyBAkAbmFtZV9oYXNoMg3274NQmpMDCgBuZXR3b3JrX2lkSFbyEwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20IEQBzdG9uZV9zbGFiX3R5cGVfMhAAcHJpc21hcmluZV9icmljawADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:crimson_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAgAACAQAbmFtZRYAbWluZWNyYWZ0OmNyaW1zb25fc2xhYgQJAG5hbWVfaGFzaKZ+EfP0ZYOZAwoAbmV0d29ya19pZAxRUWAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAgAACAQAbmFtZRYAbWluZWNyYWZ0OmNyaW1zb25fc2xhYgQJAG5hbWVfaGFzaKZ+EfP0ZYOZAwoAbmV0d29ya19pZAxRUWAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:warped_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQIAgAACAQAbmFtZRUAbWluZWNyYWZ0OndhcnBlZF9zbGFiBAkAbmFtZV9oYXNo/AT0e/Z9W7UDCgBuZXR3b3JrX2lk1yq11AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQIAgAACAQAbmFtZRUAbWluZWNyYWZ0OndhcnBlZF9zbGFiBAkAbmFtZV9oYXNo/AT0e/Z9W7UDCgBuZXR3b3JrX2lk1yq11AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:blackstone_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQZAgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsYWNrc3RvbmVfc2xhYgQJAG5hbWVfaGFzaF/DD4ZUlNgtAwoAbmV0d29ya19pZGy1DjwKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQZAgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsYWNrc3RvbmVfc2xhYgQJAG5hbWVfaGFzaF/DD4ZUlNgtAwoAbmV0d29ya19pZGy1DjwKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:polished_blackstone_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQkAgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfc2xhYgQJAG5hbWVfaGFzaDYnuUs86EWfAwoAbmV0d29ya19pZJj2bXIKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQkAgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfc2xhYgQJAG5hbWVfaGFzaDYnuUs86EWfAwoAbmV0d29ya19pZJj2bXIKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:polished_blackstone_brick_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQbAgAACAQAbmFtZSgAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfc2xhYgQJAG5hbWVfaGFzaKySLqvHc4xXAwoAbmV0d29ya19pZOyWX94KBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQbAgAACAQAbmFtZSgAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfc2xhYgQJAG5hbWVfaGFzaKySLqvHc4xXAwoAbmV0d29ya19pZOyWX94KBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:cut_copper_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRoAgAACAQAbmFtZRkAbWluZWNyYWZ0OmN1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaDsNpb2qs4iBAwoAbmV0d29ya19pZOTm2nsKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRoAgAACAQAbmFtZRkAbWluZWNyYWZ0OmN1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaDsNpb2qs4iBAwoAbmV0d29ya19pZOTm2nsKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:exposed_cut_copper_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRpAgAACAQAbmFtZSEAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcl9zbGFiBAkAbmFtZV9oYXNoahQ5OwIQb7kDCgBuZXR3b3JrX2lkrUlZLwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRpAgAACAQAbmFtZSEAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcl9zbGFiBAkAbmFtZV9oYXNoahQ5OwIQb7kDCgBuZXR3b3JrX2lkrUlZLwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:weathered_cut_copper_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRqAgAACAQAbmFtZSMAbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyX3NsYWIECQBuYW1lX2hhc2hBIuGIOVVXogMKAG5ldHdvcmtfaWQgnaDiCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRqAgAACAQAbmFtZSMAbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyX3NsYWIECQBuYW1lX2hhc2hBIuGIOVVXogMKAG5ldHdvcmtfaWQgnaDiCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:oxidized_cut_copper_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRrAgAACAQAbmFtZSIAbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaOptj9ycfpaDAwoAbmV0d29ya19pZMzFSRgKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRrAgAACAQAbmFtZSIAbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaOptj9ycfpaDAwoAbmV0d29ya19pZMzFSRgKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:waxed_cut_copper_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRsAgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaAlx6DZOCTHzAwoAbmV0d29ya19pZFRBvDAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRsAgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaAlx6DZOCTHzAwoAbmV0d29ya19pZFRBvDAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:waxed_exposed_cut_copper_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRtAgAACAQAbmFtZScAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcl9zbGFiBAkAbmFtZV9oYXNo3KqS5OnhtRIDCgBuZXR3b3JrX2lkHTGcTgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRtAgAACAQAbmFtZScAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcl9zbGFiBAkAbmFtZV9oYXNo3KqS5OnhtRIDCgBuZXR3b3JrX2lkHTGcTgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:waxed_weathered_cut_copper_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRuAgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyX3NsYWIECQBuYW1lX2hhc2gzZ1oX0HCFtwMKAG5ldHdvcmtfaWSgJR+XCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRuAgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyX3NsYWIECQBuYW1lX2hhc2gzZ1oX0HCFtwMKAG5ldHdvcmtfaWSgJR+XCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:waxed_oxidized_cut_copper_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTAAgAACAQAbmFtZSgAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaMjjTnLu1KcqAwoAbmV0d29ya19pZIxsnFYKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTAAgAACAQAbmFtZSgAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaMjjTnLu1KcqAwoAbmV0d29ya19pZIxsnFYKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:cobbled_deepslate_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR7AgAACAQAbmFtZSAAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3NsYWIECQBuYW1lX2hhc2gwJIVWK1TM2QMKAG5ldHdvcmtfaWTYAoX5CgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR7AgAACAQAbmFtZSAAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3NsYWIECQBuYW1lX2hhc2gwJIVWK1TM2QMKAG5ldHdvcmtfaWTYAoX5CgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:polished_deepslate_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR/AgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV9zbGFiBAkAbmFtZV9oYXNoC/Adiz8k6RYDCgBuZXR3b3JrX2lkuFYMAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR/AgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV9zbGFiBAkAbmFtZV9oYXNoC/Adiz8k6RYDCgBuZXR3b3JrX2lkuFYMAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:deepslate_tile_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3NsYWIECQBuYW1lX2hhc2hPydV6emzIXAMKAG5ldHdvcmtfaWQwlbFCCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3NsYWIECQBuYW1lX2hhc2hPydV6emzIXAMKAG5ldHdvcmtfaWQwlbFCCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:deepslate_brick_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSHAgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja19zbGFiBAkAbmFtZV9oYXNoSv62V7iw10UDCgBuZXR3b3JrX2lkWMoragoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSHAgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja19zbGFiBAkAbmFtZV9oYXNoSv62V7iw10UDCgBuZXR3b3JrX2lkWMoragoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:mud_brick_slab", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAgAACAQAbmFtZRgAbWluZWNyYWZ0Om11ZF9icmlja19zbGFiBAkAbmFtZV9oYXNoq/tGBQWkv08DCgBuZXR3b3JrX2lkl4nnMwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAgAACAQAbmFtZRgAbWluZWNyYWZ0Om11ZF9icmlja19zbGFiBAkAbmFtZV9oYXNoq/tGBQWkv08DCgBuZXR3b3JrX2lkl4nnMwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:brick_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQtAAAACAQAbmFtZRUAbWluZWNyYWZ0OmJyaWNrX2Jsb2NrBAkAbmFtZV9oYXNo5Qc2E005S3oDCgBuZXR3b3JrX2lkqeGWRgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQtAAAACAQAbmFtZRUAbWluZWNyYWZ0OmJyaWNrX2Jsb2NrBAkAbmFtZV9oYXNo5Qc2E005S3oDCgBuZXR3b3JrX2lkqeGWRgoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:chiseled_nether_bricks", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQtAgAACAQAbmFtZSAAbWluZWNyYWZ0OmNoaXNlbGVkX25ldGhlcl9icmlja3MECQBuYW1lX2hhc2g31SBPTcUK1QMKAG5ldHdvcmtfaWS8TJ+TCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQtAgAACAQAbmFtZSAAbWluZWNyYWZ0OmNoaXNlbGVkX25ldGhlcl9icmlja3MECQBuYW1lX2hhc2g31SBPTcUK1QMKAG5ldHdvcmtfaWS8TJ+TCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:cracked_nether_bricks", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQuAgAACAQAbmFtZR8AbWluZWNyYWZ0OmNyYWNrZWRfbmV0aGVyX2JyaWNrcwQJAG5hbWVfaGFzaAdC6eKzXT5tAwoAbmV0d29ya19pZIUSejwKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQuAgAACAQAbmFtZR8AbWluZWNyYWZ0OmNyYWNrZWRfbmV0aGVyX2JyaWNrcwQJAG5hbWVfaGFzaAdC6eKzXT5tAwoAbmV0d29ya19pZIUSejwKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:quartz_bricks", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQvAgAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9icmlja3MECQBuYW1lX2hhc2jSZO590dd8sAMKAG5ldHdvcmtfaWSc5xCLCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQvAgAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9icmlja3MECQBuYW1lX2hhc2jSZO590dd8sAMKAG5ldHdvcmtfaWSc5xCLCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:stonebrick", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAAAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWQ5kni1CgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQcAZGVmYXVsdAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAAAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWQ5kni1CgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQcAZGVmYXVsdAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:stonebrick", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAAAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWTDw813CgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQUAbW9zc3kAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAAAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWTDw813CgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQUAbW9zc3kAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:stonebrick", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAAAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWSTvQGECgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQcAY3JhY2tlZAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAAAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWSTvQGECgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQcAY3JhY2tlZAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:stonebrick", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAAAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWQIM0OwCgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQgAY2hpc2VsZWQAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAAAACAQAbmFtZRQAbWluZWNyYWZ0OnN0b25lYnJpY2sECQBuYW1lX2hhc2ii9DAAVXKptwMKAG5ldHdvcmtfaWQIM0OwCgYAc3RhdGVzCBAAc3RvbmVfYnJpY2tfdHlwZQgAY2hpc2VsZWQAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:end_bricks", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTOAAAACAQAbmFtZRQAbWluZWNyYWZ0OmVuZF9icmlja3MECQBuYW1lX2hhc2hIUFfxNLZaFgMKAG5ldHdvcmtfaWQ/vDihCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTOAAAACAQAbmFtZRQAbWluZWNyYWZ0OmVuZF9icmlja3MECQBuYW1lX2hhc2hIUFfxNLZaFgMKAG5ldHdvcmtfaWQ/vDihCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:prismarine", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAAAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWSH021WCgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBgBicmlja3MAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAAAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWSH021WCgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBgBicmlja3MAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:polished_blackstone_bricks", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQRAgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tzBAkAbmFtZV9oYXNoIHgsgIdzKXcDCgBuZXR3b3JrX2lkUw9b3woGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQRAgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tzBAkAbmFtZV9oYXNoIHgsgIdzKXcDCgBuZXR3b3JrX2lkUw9b3woGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:cracked_polished_blackstone_bricks", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQXAgAACAQAbmFtZSwAbWluZWNyYWZ0OmNyYWNrZWRfcG9saXNoZWRfYmxhY2tzdG9uZV9icmlja3MECQBuYW1lX2hhc2jQIO1GQDk80AMKAG5ldHdvcmtfaWQ3UlRYCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQXAgAACAQAbmFtZSwAbWluZWNyYWZ0OmNyYWNrZWRfcG9saXNoZWRfYmxhY2tzdG9uZV9icmlja3MECQBuYW1lX2hhc2jQIO1GQDk80AMKAG5ldHdvcmtfaWQ3UlRYCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:gilded_blackstone", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAgAACAQAbmFtZRsAbWluZWNyYWZ0OmdpbGRlZF9ibGFja3N0b25lBAkAbmFtZV9oYXNoNoWt1ocG0HEDCgBuZXR3b3JrX2lktL8gUwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAgAACAQAbmFtZRsAbWluZWNyYWZ0OmdpbGRlZF9ibGFja3N0b25lBAkAbmFtZV9oYXNoNoWt1ocG0HEDCgBuZXR3b3JrX2lktL8gUwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:chiseled_polished_blackstone", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQWAgAACAQAbmFtZSYAbWluZWNyYWZ0OmNoaXNlbGVkX3BvbGlzaGVkX2JsYWNrc3RvbmUECQBuYW1lX2hhc2gzFa+kEjCJgAMKAG5ldHdvcmtfaWR2NJX2CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQWAgAACAQAbmFtZSYAbWluZWNyYWZ0OmNoaXNlbGVkX3BvbGlzaGVkX2JsYWNrc3RvbmUECQBuYW1lX2hhc2gzFa+kEjCJgAMKAG5ldHdvcmtfaWR2NJX2CgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:deepslate_tiles", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlcwQJAG5hbWVfaGFzaGcLLx3NXAFvAwoAbmV0d29ya19pZI/G/xYKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlcwQJAG5hbWVfaGFzaGcLLx3NXAFvAwoAbmV0d29ya19pZI/G/xYKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:cracked_deepslate_tiles", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSYAgAACAQAbmFtZSEAbWluZWNyYWZ0OmNyYWNrZWRfZGVlcHNsYXRlX3RpbGVzBAkAbmFtZV9oYXNo9zWgkFuMM1QDCgBuZXR3b3JrX2lkGwY6OgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSYAgAACAQAbmFtZSEAbWluZWNyYWZ0OmNyYWNrZWRfZGVlcHNsYXRlX3RpbGVzBAkAbmFtZV9oYXNo9zWgkFuMM1QDCgBuZXR3b3JrX2lkGwY6OgoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:deepslate_bricks", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSGAgAACAQAbmFtZRoAbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja3MECQBuYW1lX2hhc2gucvFmPdZxigMKAG5ldHdvcmtfaWSH4HDPCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSGAgAACAQAbmFtZRoAbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja3MECQBuYW1lX2hhc2gucvFmPdZxigMKAG5ldHdvcmtfaWSH4HDPCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:cracked_deepslate_bricks", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSZAgAACAQAbmFtZSIAbWluZWNyYWZ0OmNyYWNrZWRfZGVlcHNsYXRlX2JyaWNrcwQJAG5hbWVfaGFzaN40aqhh9WqHAwoAbmV0d29ya19pZO9GPBQKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSZAgAACAQAbmFtZSIAbWluZWNyYWZ0OmNyYWNrZWRfZGVlcHNsYXRlX2JyaWNrcwQJAG5hbWVfaGFzaN40aqhh9WqHAwoAbmV0d29ya19pZO9GPBQKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:chiseled_deepslate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAgAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaEU7/uRG8HSBAwoAbmV0d29ya19pZEqmI0EKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAgAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaEU7/uRG8HSBAwoAbmV0d29ya19pZEqmI0EKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:cobblestone", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQEAAAACAQAbmFtZRUAbWluZWNyYWZ0OmNvYmJsZXN0b25lBAkAbmFtZV9oYXNoPoK7mGlSUz4DCgBuZXR3b3JrX2lkLm7RZwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQEAAAACAQAbmFtZRUAbWluZWNyYWZ0OmNvYmJsZXN0b25lBAkAbmFtZV9oYXNoPoK7mGlSUz4DCgBuZXR3b3JrX2lkLm7RZwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:mossy_cobblestone", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQwAAAACAQAbmFtZRsAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lBAkAbmFtZV9oYXNoGJ67FCbkChMDCgBuZXR3b3JrX2lk/pYs1AoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQwAAAACAQAbmFtZRsAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lBAkAbmFtZV9oYXNoGJ67FCbkChMDCgBuZXR3b3JrX2lk/pYs1AoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:cobbled_deepslate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR6AgAACAQAbmFtZRsAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlBAkAbmFtZV9oYXNoLUz9Y/ywmLwDCgBuZXR3b3JrX2lkNwzZ+AoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR6AgAACAQAbmFtZRsAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlBAkAbmFtZV9oYXNoLUz9Y/ywmLwDCgBuZXR3b3JrX2lkNwzZ+AoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:smooth_stone", - "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AQAACAQAbmFtZRYAbWluZWNyYWZ0OnNtb290aF9zdG9uZQQJAG5hbWVfaGFzaMwf87/JaTNvAwoAbmV0d29ya19pZLkZICEKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AQAACAQAbmFtZRYAbWluZWNyYWZ0OnNtb290aF9zdG9uZQQJAG5hbWVfaGFzaMwf87/JaTNvAwoAbmV0d29ya19pZLkZICEKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:sandstone", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZB2wApMKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUHAGRlZmF1bHQAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZB2wApMKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUHAGRlZmF1bHQAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:sandstone", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZB7E+eQKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGULAGhlaXJvZ2x5cGhzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZB7E+eQKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGULAGhlaXJvZ2x5cGhzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:sandstone", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZFQnDaEKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUDAGN1dAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZFQnDaEKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUDAGN1dAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:sandstone", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZPO4A3IKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUGAHNtb290aAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZPO4A3IKBgBzdGF0ZXMIDwBzYW5kX3N0b25lX3R5cGUGAHNtb290aAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:red_sandstone", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWRhNYiFCgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWRhNYiFCgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:red_sandstone", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTqXJr1CgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlCwBoZWlyb2dseXBocwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTqXJr1CgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlCwBoZWlyb2dseXBocwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:red_sandstone", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTQRGkFCgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlAwBjdXQAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTQRGkFCgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlAwBjdXQAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:red_sandstone", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTvAHWDCgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlBgBzbW9vdGgAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWTvAHWDCgYAc3RhdGVzCA8Ac2FuZF9zdG9uZV90eXBlBgBzbW9vdGgAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:coal_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWStAAAACAQAbmFtZRQAbWluZWNyYWZ0OmNvYWxfYmxvY2sECQBuYW1lX2hhc2jH8QQP3t5PiAMKAG5ldHdvcmtfaWRo+sR+CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWStAAAACAQAbmFtZRQAbWluZWNyYWZ0OmNvYWxfYmxvY2sECQBuYW1lX2hhc2jH8QQP3t5PiAMKAG5ldHdvcmtfaWRo+sR+CgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:dried_kelp_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAQAACAQAbmFtZRoAbWluZWNyYWZ0OmRyaWVkX2tlbHBfYmxvY2sECQBuYW1lX2hhc2iRoucexkrl8wMKAG5ldHdvcmtfaWQQCCrvCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAQAACAQAbmFtZRoAbWluZWNyYWZ0OmRyaWVkX2tlbHBfYmxvY2sECQBuYW1lX2hhc2iRoucexkrl8wMKAG5ldHdvcmtfaWQQCCrvCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:gold_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQpAAAACAQAbmFtZRQAbWluZWNyYWZ0OmdvbGRfYmxvY2sECQBuYW1lX2hhc2iYLshvjtXzFwMKAG5ldHdvcmtfaWTDJGBcCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQpAAAACAQAbmFtZRQAbWluZWNyYWZ0OmdvbGRfYmxvY2sECQBuYW1lX2hhc2iYLshvjtXzFwMKAG5ldHdvcmtfaWTDJGBcCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:iron_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQqAAAACAQAbmFtZRQAbWluZWNyYWZ0Omlyb25fYmxvY2sECQBuYW1lX2hhc2jYINmJQbvV/gMKAG5ldHdvcmtfaWRf7AbICgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQqAAAACAQAbmFtZRQAbWluZWNyYWZ0Omlyb25fYmxvY2sECQBuYW1lX2hhc2jYINmJQbvV/gMKAG5ldHdvcmtfaWRf7AbICgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:copper_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRTAgAACAQAbmFtZRYAbWluZWNyYWZ0OmNvcHBlcl9ibG9jawQJAG5hbWVfaGFzaDVxnehsGaZ1AwoAbmV0d29ya19pZIiUodwKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRTAgAACAQAbmFtZRYAbWluZWNyYWZ0OmNvcHBlcl9ibG9jawQJAG5hbWVfaGFzaDVxnehsGaZ1AwoAbmV0d29ya19pZIiUodwKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" + }, + { + "id": "minecraft:copper_door" + }, + { + "id": "minecraft:copper_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQXBAAACAQAbmFtZRkAbWluZWNyYWZ0OmNvcHBlcl90cmFwZG9vcgQJAG5hbWVfaGFzaO9fXio+svKVAwoAbmV0d29ya19pZMCoRjEKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uAwAVAQA=" + }, + { + "id": "minecraft:copper_grate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT/AwAACAQAbmFtZRYAbWluZWNyYWZ0OmNvcHBlcl9ncmF0ZQQJAG5hbWVfaGFzaC/JEFOWnmEcAwoAbmV0d29ya19pZC6YiiMKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:exposed_copper", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRUAgAACAQAbmFtZRgAbWluZWNyYWZ0OmV4cG9zZWRfY29wcGVyBAkAbmFtZV9oYXNoQH3Fukmu3CEDCgBuZXR3b3JrX2lk72jFIwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRUAgAACAQAbmFtZRgAbWluZWNyYWZ0OmV4cG9zZWRfY29wcGVyBAkAbmFtZV9oYXNoQH3Fukmu3CEDCgBuZXR3b3JrX2lk72jFIwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" + }, + { + "id": "minecraft:exposed_copper_door" + }, + { + "id": "minecraft:exposed_copper_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYBAAACAQAbmFtZSEAbWluZWNyYWZ0OmV4cG9zZWRfY29wcGVyX3RyYXBkb29yBAkAbmFtZV9oYXNoYhDFUysN7qUDCgBuZXR3b3JrX2lkMzwGJgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24DABUBAA==" + }, + { + "id": "minecraft:exposed_copper_grate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQABAAACAQAbmFtZR4AbWluZWNyYWZ0OmV4cG9zZWRfY29wcGVyX2dyYXRlBAkAbmFtZV9oYXNolFIBYLYU0IcDCgBuZXR3b3JrX2lk4UqptAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:weathered_copper", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRVAgAACAQAbmFtZRoAbWluZWNyYWZ0OndlYXRoZXJlZF9jb3BwZXIECQBuYW1lX2hhc2hJCQXbvobv+gMKAG5ldHdvcmtfaWQwM0lJCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRVAgAACAQAbmFtZRoAbWluZWNyYWZ0OndlYXRoZXJlZF9jb3BwZXIECQBuYW1lX2hhc2hJCQXbvobv+gMKAG5ldHdvcmtfaWQwM0lJCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" + }, + { + "id": "minecraft:weathered_copper_door" + }, + { + "id": "minecraft:weathered_copper_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQZBAAACAQAbmFtZSMAbWluZWNyYWZ0OndlYXRoZXJlZF9jb3BwZXJfdHJhcGRvb3IECQBuYW1lX2hhc2hFnEC282a1tgMKAG5ldHdvcmtfaWTk70oiCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgMAFQEA" + }, + { + "id": "minecraft:weathered_copper_grate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBBAAACAQAbmFtZSAAbWluZWNyYWZ0OndlYXRoZXJlZF9jb3BwZXJfZ3JhdGUECQBuYW1lX2hhc2jB3o8enlv1RgMKAG5ldHdvcmtfaWRih2pOCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:oxidized_copper", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRWAgAACAQAbmFtZRkAbWluZWNyYWZ0Om94aWRpemVkX2NvcHBlcgQJAG5hbWVfaGFzaMDtJqR0G5Y7AwoAbmV0d29ya19pZGjN8bUKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRWAgAACAQAbmFtZRkAbWluZWNyYWZ0Om94aWRpemVkX2NvcHBlcgQJAG5hbWVfaGFzaMDtJqR0G5Y7AwoAbmV0d29ya19pZGjN8bUKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" + }, + { + "id": "minecraft:oxidized_copper_door" + }, + { + "id": "minecraft:oxidized_copper_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQaBAAACAQAbmFtZSIAbWluZWNyYWZ0Om94aWRpemVkX2NvcHBlcl90cmFwZG9vcgQJAG5hbWVfaGFzaOJpG/XFexVwAwoAbmV0d29ya19pZPhi0J4KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uAwAVAQA=" + }, + { + "id": "minecraft:oxidized_copper_grate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCBAAACAQAbmFtZR8AbWluZWNyYWZ0Om94aWRpemVkX2NvcHBlcl9ncmF0ZQQJAG5hbWVfaGFzaBRfNhyndve7AwoAbmV0d29ya19pZKY2cnEKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:waxed_copper", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRXAgAACAQAbmFtZRYAbWluZWNyYWZ0OndheGVkX2NvcHBlcgQJAG5hbWVfaGFzaPF+FG6Eh5fsAwoAbmV0d29ya19pZIjtz/0KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRXAgAACAQAbmFtZRYAbWluZWNyYWZ0OndheGVkX2NvcHBlcgQJAG5hbWVfaGFzaPF+FG6Eh5fsAwoAbmV0d29ya19pZIjtz/0KBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" + }, + { + "id": "minecraft:waxed_copper_door" + }, + { + "id": "minecraft:waxed_copper_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQbBAAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX2NvcHBlcl90cmFwZG9vcgQJAG5hbWVfaGFzaO0JUKUHqNU6AwoAbmV0d29ya19pZJC3ZuMKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uAwAVAQA=" + }, + { + "id": "minecraft:waxed_copper_grate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDBAAACAQAbmFtZRwAbWluZWNyYWZ0OndheGVkX2NvcHBlcl9ncmF0ZQQJAG5hbWVfaGFzaDmC92M2RO+HAwoAbmV0d29ya19pZH4og2AKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:waxed_exposed_copper", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRYAgAACAQAbmFtZR4AbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY29wcGVyBAkAbmFtZV9oYXNoig8IOc+SCikDCgBuZXR3b3JrX2lklz8yWQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRYAgAACAQAbmFtZR4AbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY29wcGVyBAkAbmFtZV9oYXNoig8IOc+SCikDCgBuZXR3b3JrX2lklz8yWQoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" + }, + { + "id": "minecraft:waxed_exposed_copper_door" + }, + { + "id": "minecraft:waxed_exposed_copper_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQcBAAACAQAbmFtZScAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY29wcGVyX3RyYXBkb29yBAkAbmFtZV9oYXNoBHHxCpkUzpgDCgBuZXR3b3JrX2lkw2XBGQoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24DABUBAA==" + }, + { + "id": "minecraft:waxed_exposed_copper_grate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQEBAAACAQAbmFtZSQAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY29wcGVyX2dyYXRlBAkAbmFtZV9oYXNoWmd6B+hWwiEDCgBuZXR3b3JrX2lk8d4ZQwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:waxed_weathered_copper", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRZAgAACAQAbmFtZSAAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jb3BwZXIECQBuYW1lX2hhc2gjtPq8MOdvKgMKAG5ldHdvcmtfaWSQ9Ln9CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRZAgAACAQAbmFtZSAAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jb3BwZXIECQBuYW1lX2hhc2gjtPq8MOdvKgMKAG5ldHdvcmtfaWSQ9Ln9CgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" + }, + { + "id": "minecraft:waxed_weathered_copper_door" + }, + { + "id": "minecraft:waxed_weathered_copper_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQdBAAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jb3BwZXJfdHJhcGRvb3IECQBuYW1lX2hhc2gH9Fi3JCF4egMKAG5ldHdvcmtfaWRkGU6TCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgMAFQEA" + }, + { + "id": "minecraft:waxed_weathered_copper_grate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQFBAAACAQAbmFtZSYAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jb3BwZXJfZ3JhdGUECQBuYW1lX2hhc2hXfilVFDAiYQMKAG5ldHdvcmtfaWQqTGC1CgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:waxed_oxidized_copper", - "block_state_b64": "CgAAAwgAYmxvY2tfaWS9AgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NvcHBlcgQJAG5hbWVfaGFzaMaORhsO+LzjAwoAbmV0d29ya19pZJhGfLEKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWS9AgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NvcHBlcgQJAG5hbWVfaGFzaMaORhsO+LzjAwoAbmV0d29ya19pZJhGfLEKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" + }, + { + "id": "minecraft:waxed_oxidized_copper_door" + }, + { + "id": "minecraft:waxed_oxidized_copper_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQeBAAACAQAbmFtZSgAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NvcHBlcl90cmFwZG9vcgQJAG5hbWVfaGFzaNA/q9qAy6Z9AwoAbmV0d29ya19pZDgExS8KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uAwAVAQA=" + }, + { + "id": "minecraft:waxed_oxidized_copper_grate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGBAAACAQAbmFtZSUAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NvcHBlcl9ncmF0ZQQJAG5hbWVfaGFzaEbeMT605GP4AwoAbmV0d29ya19pZOZjpkkKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:cut_copper", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRaAgAACAQAbmFtZRQAbWluZWNyYWZ0OmN1dF9jb3BwZXIECQBuYW1lX2hhc2hAfN3NGax3eAMKAG5ldHdvcmtfaWTnFBtYCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRaAgAACAQAbmFtZRQAbWluZWNyYWZ0OmN1dF9jb3BwZXIECQBuYW1lX2hhc2hAfN3NGax3eAMKAG5ldHdvcmtfaWTnFBtYCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:exposed_cut_copper", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRbAgAACAQAbmFtZRwAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcgQJAG5hbWVfaGFzaA85G3yv/w6pAwoAbmV0d29ya19pZMQhr0QKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRbAgAACAQAbmFtZRwAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcgQJAG5hbWVfaGFzaA85G3yv/w6pAwoAbmV0d29ya19pZMQhr0QKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:weathered_cut_copper", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRcAgAACAQAbmFtZR4AbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyBAkAbmFtZV9oYXNoVgRV0fBaz88DCgBuZXR3b3JrX2lk/0cYugoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRcAgAACAQAbmFtZR4AbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyBAkAbmFtZV9oYXNoVgRV0fBaz88DCgBuZXR3b3JrX2lk/0cYugoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:oxidized_cut_copper", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRdAgAACAQAbmFtZR0AbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2iP8WmFWOkriwMKAG5ldHdvcmtfaWQPdce7CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRdAgAACAQAbmFtZR0AbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2iP8WmFWOkriwMKAG5ldHdvcmtfaWQPdce7CgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:waxed_cut_copper", - "block_state_b64": "CgAAAwgAYmxvY2tfaWReAgAACAQAbmFtZRoAbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2jumiwOZIqv2AMKAG5ldHdvcmtfaWQvuxx9CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWReAgAACAQAbmFtZRoAbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2jumiwOZIqv2AMKAG5ldHdvcmtfaWQvuxx9CgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:waxed_exposed_cut_copper", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRfAgAACAQAbmFtZSIAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcgQJAG5hbWVfaGFzaPE/OfK6IoVMAwoAbmV0d29ya19pZHy5HkcKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRfAgAACAQAbmFtZSIAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcgQJAG5hbWVfaGFzaPE/OfK6IoVMAwoAbmV0d29ya19pZHy5HkcKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:waxed_weathered_cut_copper", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRgAgAACAQAbmFtZSQAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyBAkAbmFtZV9oYXNoCA1xDp11bnwDCgBuZXR3b3JrX2lkDyEDVQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRgAgAACAQAbmFtZSQAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyBAkAbmFtZV9oYXNoCA1xDp11bnwDCgBuZXR3b3JrX2lkDyEDVQoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:waxed_oxidized_cut_copper", - "block_state_b64": "CgAAAwgAYmxvY2tfaWS+AgAACAQAbmFtZSMAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2i1pZAsZYHLDAMKAG5ldHdvcmtfaWQ/wSkCCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWS+AgAACAQAbmFtZSMAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2i1pZAsZYHLDAMKAG5ldHdvcmtfaWQ/wSkCCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" + }, + { + "id": "minecraft:chiseled_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT3AwAACAQAbmFtZRkAbWluZWNyYWZ0OmNoaXNlbGVkX2NvcHBlcgQJAG5hbWVfaGFzaIsW5pmpJEuQAwoAbmV0d29ya19pZHetwrkKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" + }, + { + "id": "minecraft:exposed_chiseled_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT4AwAACAQAbmFtZSEAbWluZWNyYWZ0OmV4cG9zZWRfY2hpc2VsZWRfY29wcGVyBAkAbmFtZV9oYXNoOvrLJ0UowbgDCgBuZXR3b3JrX2lkZj7cPwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" + }, + { + "id": "minecraft:weathered_chiseled_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT5AwAACAQAbmFtZSMAbWluZWNyYWZ0OndlYXRoZXJlZF9jaGlzZWxlZF9jb3BwZXIECQBuYW1lX2hhc2hh+42XlsWvGAMKAG5ldHdvcmtfaWS7Cy59CgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" + }, + { + "id": "minecraft:oxidized_chiseled_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT6AwAACAQAbmFtZSIAbWluZWNyYWZ0Om94aWRpemVkX2NoaXNlbGVkX2NvcHBlcgQJAG5hbWVfaGFzaLpTIsnfluiCAwoAbmV0d29ya19pZB9/jS8KBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" + }, + { + "id": "minecraft:waxed_chiseled_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT7AwAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX2NoaXNlbGVkX2NvcHBlcgQJAG5hbWVfaGFzaFnXvXY5OinzAwoAbmV0d29ya19pZAcKtHsKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" + }, + { + "id": "minecraft:waxed_exposed_chiseled_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT8AwAACAQAbmFtZScAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY2hpc2VsZWRfY29wcGVyBAkAbmFtZV9oYXNoHJdq+Pph6hMDCgBuZXR3b3JrX2lkdge7IAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" + }, + { + "id": "minecraft:waxed_oxidized_chiseled_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT9AwAACAQAbmFtZSgAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NoaXNlbGVkX2NvcHBlcgQJAG5hbWVfaGFzaMj49OvlTpgCAwoAbmV0d29ya19pZN/r+roKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" + }, + { + "id": "minecraft:waxed_weathered_chiseled_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT+AwAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jaGlzZWxlZF9jb3BwZXIECQBuYW1lX2hhc2hzuO+Sg9LYQwMKAG5ldHdvcmtfaWQ7AN7iCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" + }, + { + "id": "minecraft:copper_bulb", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHBAAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcHBlcl9idWxiBAkAbmFtZV9oYXNo41TimHOsMWcDCgBuZXR3b3JrX2lkJnZvAgoGAHN0YXRlcwEDAGxpdAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgMAFQEA" + }, + { + "id": "minecraft:exposed_copper_bulb", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQIBAAACAQAbmFtZR0AbWluZWNyYWZ0OmV4cG9zZWRfY29wcGVyX2J1bGIECQBuYW1lX2hhc2g++f1wYLLCrAMKAG5ldHdvcmtfaWRLdMmGCgYAc3RhdGVzAQMAbGl0AAELAHBvd2VyZWRfYml0AAADBwB2ZXJzaW9uAwAVAQA=" + }, + { + "id": "minecraft:weathered_copper_bulb", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQJBAAACAQAbmFtZR8AbWluZWNyYWZ0OndlYXRoZXJlZF9jb3BwZXJfYnVsYgQJAG5hbWVfaGFzaMEtsYfwRTXlAwoAbmV0d29ya19pZAp51LQKBgBzdGF0ZXMBAwBsaXQAAQsAcG93ZXJlZF9iaXQAAAMHAHZlcnNpb24DABUBAA==" + }, + { + "id": "minecraft:oxidized_copper_bulb", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQKBAAACAQAbmFtZR4AbWluZWNyYWZ0Om94aWRpemVkX2NvcHBlcl9idWxiBAkAbmFtZV9oYXNovnrBQZs8nDIDCgBuZXR3b3JrX2lkPsj0AAoGAHN0YXRlcwEDAGxpdAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgMAFQEA" + }, + { + "id": "minecraft:waxed_copper_bulb", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQLBAAACAQAbmFtZRsAbWluZWNyYWZ0OndheGVkX2NvcHBlcl9idWxiBAkAbmFtZV9oYXNoGTg6TYllMiIDCgBuZXR3b3JrX2lk9m0WhgoGAHN0YXRlcwEDAGxpdAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgMAFQEA" + }, + { + "id": "minecraft:waxed_exposed_copper_bulb", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQMBAAACAQAbmFtZSMAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY29wcGVyX2J1bGIECQBuYW1lX2hhc2gI6xkPcvBDVwMKAG5ldHdvcmtfaWR7BRcACgYAc3RhdGVzAQMAbGl0AAELAHBvd2VyZWRfYml0AAADBwB2ZXJzaW9uAwAVAQA=" + }, + { + "id": "minecraft:waxed_weathered_copper_bulb", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQNBAAACAQAbmFtZSUAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jb3BwZXJfYnVsYgQJAG5hbWVfaGFzaMsUnmp3/VqVAwoAbmV0d29ya19pZEoworoKBgBzdGF0ZXMBAwBsaXQAAQsAcG93ZXJlZF9iaXQAAAMHAHZlcnNpb24DABUBAA==" + }, + { + "id": "minecraft:waxed_oxidized_copper_bulb", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQOBAAACAQAbmFtZSQAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NvcHBlcl9idWxiBAkAbmFtZV9oYXNoBFKxY3fjVq4DCgBuZXR3b3JrX2lkzrJ6aAoGAHN0YXRlcwEDAGxpdAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:emerald_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAAAACAQAbmFtZRcAbWluZWNyYWZ0OmVtZXJhbGRfYmxvY2sECQBuYW1lX2hhc2hK6QunqJznNAMKAG5ldHdvcmtfaWRk5+otCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAAAACAQAbmFtZRcAbWluZWNyYWZ0OmVtZXJhbGRfYmxvY2sECQBuYW1lX2hhc2hK6QunqJznNAMKAG5ldHdvcmtfaWRk5+otCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:diamond_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ5AAAACAQAbmFtZRcAbWluZWNyYWZ0OmRpYW1vbmRfYmxvY2sECQBuYW1lX2hhc2iGKrxuvkytFQMKAG5ldHdvcmtfaWQQeQZXCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ5AAAACAQAbmFtZRcAbWluZWNyYWZ0OmRpYW1vbmRfYmxvY2sECQBuYW1lX2hhc2iGKrxuvkytFQMKAG5ldHdvcmtfaWQQeQZXCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:lapis_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQWAAAACAQAbmFtZRUAbWluZWNyYWZ0OmxhcGlzX2Jsb2NrBAkAbmFtZV9oYXNoDZ44xdb2zVoDCgBuZXR3b3JrX2lktVy0BAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQWAAAACAQAbmFtZRUAbWluZWNyYWZ0OmxhcGlzX2Jsb2NrBAkAbmFtZV9oYXNoDZ44xdb2zVoDCgBuZXR3b3JrX2lktVy0BAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:raw_iron_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTCAgAACAQAbmFtZRgAbWluZWNyYWZ0OnJhd19pcm9uX2Jsb2NrBAkAbmFtZV9oYXNo9XyzNIQXxvwDCgBuZXR3b3JrX2lknms1QAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTCAgAACAQAbmFtZRgAbWluZWNyYWZ0OnJhd19pcm9uX2Jsb2NrBAkAbmFtZV9oYXNo9XyzNIQXxvwDCgBuZXR3b3JrX2lknms1QAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:raw_copper_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTDAgAACAQAbmFtZRoAbWluZWNyYWZ0OnJhd19jb3BwZXJfYmxvY2sECQBuYW1lX2hhc2hw1KG0TNUGgwMKAG5ldHdvcmtfaWS1vGo/CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTDAgAACAQAbmFtZRoAbWluZWNyYWZ0OnJhd19jb3BwZXJfYmxvY2sECQBuYW1lX2hhc2hw1KG0TNUGgwMKAG5ldHdvcmtfaWS1vGo/CgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:raw_gold_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTEAgAACAQAbmFtZRgAbWluZWNyYWZ0OnJhd19nb2xkX2Jsb2NrBAkAbmFtZV9oYXNo6YuwuLwfOBwDCgBuZXR3b3JrX2lkLiQ5gQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTEAgAACAQAbmFtZRgAbWluZWNyYWZ0OnJhd19nb2xkX2Jsb2NrBAkAbmFtZV9oYXNo6YuwuLwfOBwDCgBuZXR3b3JrX2lkLiQ5gQoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:quartz_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAAAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZEupC1AKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQcAZGVmYXVsdAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAAAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZEupC1AKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQcAZGVmYXVsdAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:quartz_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAAAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZM97+l0KBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQUAbGluZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAAAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZM97+l0KBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQUAbGluZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:quartz_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAAAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZCbTfssKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQgAY2hpc2VsZWQICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAAAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZCbTfssKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQgAY2hpc2VsZWQICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:quartz_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAAAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZJss8V0KBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQYAc21vb3RoCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAAAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZJss8V0KBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQYAc21vb3RoCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:prismarine", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAAAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWRFIsoGCgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAAAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWRFIsoGCgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:prismarine", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAAAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWTDNWOvCgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBABkYXJrAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAAAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWTDNWOvCgYAc3RhdGVzCBUAcHJpc21hcmluZV9ibG9ja190eXBlBABkYXJrAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:slime", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAAAACAQAbmFtZQ8AbWluZWNyYWZ0OnNsaW1lBAkAbmFtZV9oYXNoHJiEEJx+JlkDCgBuZXR3b3JrX2lkfgfVzAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAAAACAQAbmFtZQ8AbWluZWNyYWZ0OnNsaW1lBAkAbmFtZV9oYXNoHJiEEJx+JlkDCgBuZXR3b3JrX2lkfgfVzAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:honey_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTbAQAACAQAbmFtZRUAbWluZWNyYWZ0OmhvbmV5X2Jsb2NrBAkAbmFtZV9oYXNo9zLYSUlelywDCgBuZXR3b3JrX2lko+dyWgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTbAQAACAQAbmFtZRUAbWluZWNyYWZ0OmhvbmV5X2Jsb2NrBAkAbmFtZV9oYXNo9zLYSUlelywDCgBuZXR3b3JrX2lko+dyWgoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:honeycomb_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAQAACAQAbmFtZRkAbWluZWNyYWZ0OmhvbmV5Y29tYl9ibG9jawQJAG5hbWVfaGFzaASIPuOCYd1oAwoAbmV0d29ya19pZKys4n4KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAQAACAQAbmFtZRkAbWluZWNyYWZ0OmhvbmV5Y29tYl9ibG9jawQJAG5hbWVfaGFzaASIPuOCYd1oAwoAbmV0d29ya19pZKys4n4KBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:hay_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAAAACAQAbmFtZRMAbWluZWNyYWZ0OmhheV9ibG9jawQJAG5hbWVfaGFzaIB2VxKxX8EpAwoAbmV0d29ya19pZKuQSloKBgBzdGF0ZXMDCgBkZXByZWNhdGVkAAAAAAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAAAACAQAbmFtZRMAbWluZWNyYWZ0OmhheV9ibG9jawQJAG5hbWVfaGFzaIB2VxKxX8EpAwoAbmV0d29ya19pZKuQSloKBgBzdGF0ZXMDCgBkZXByZWNhdGVkAAAAAAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:bone_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTYAAAACAQAbmFtZRQAbWluZWNyYWZ0OmJvbmVfYmxvY2sECQBuYW1lX2hhc2i4ZX576W9AWgMKAG5ldHdvcmtfaWTWGacQCgYAc3RhdGVzAwoAZGVwcmVjYXRlZAAAAAAICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTYAAAACAQAbmFtZRQAbWluZWNyYWZ0OmJvbmVfYmxvY2sECQBuYW1lX2hhc2i4ZX576W9AWgMKAG5ldHdvcmtfaWTWGacQCgYAc3RhdGVzAwoAZGVwcmVjYXRlZAAAAAAICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:nether_brick", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRwAAAACAQAbmFtZRYAbWluZWNyYWZ0Om5ldGhlcl9icmljawQJAG5hbWVfaGFzaMxcRiheU+nXAwoAbmV0d29ya19pZMkmzloKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRwAAAACAQAbmFtZRYAbWluZWNyYWZ0Om5ldGhlcl9icmljawQJAG5hbWVfaGFzaMxcRiheU+nXAwoAbmV0d29ya19pZMkmzloKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:red_nether_brick", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAAAACAQAbmFtZRoAbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2sECQBuYW1lX2hhc2j8pRO4LfoECAMKAG5ldHdvcmtfaWRpdF0YCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAAAACAQAbmFtZRoAbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2sECQBuYW1lX2hhc2j8pRO4LfoECAMKAG5ldHdvcmtfaWRpdF0YCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:netherite_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQNAgAACAQAbmFtZRkAbWluZWNyYWZ0Om5ldGhlcml0ZV9ibG9jawQJAG5hbWVfaGFzaMghh6Zib/ZKAwoAbmV0d29ya19pZIz0mq0KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQNAgAACAQAbmFtZRkAbWluZWNyYWZ0Om5ldGhlcml0ZV9ibG9jawQJAG5hbWVfaGFzaMghh6Zib/ZKAwoAbmV0d29ya19pZIz0mq0KBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:lodestone", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAQAACAQAbmFtZRMAbWluZWNyYWZ0OmxvZGVzdG9uZQQJAG5hbWVfaGFzaJ2gmHOTlXv8AwoAbmV0d29ya19pZEfgB4wKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAQAACAQAbmFtZRMAbWluZWNyYWZ0OmxvZGVzdG9uZQQJAG5hbWVfaGFzaJ2gmHOTlXv8AwoAbmV0d29ya19pZEfgB4wKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:white_wool", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQjAAAACAQAbmFtZRQAbWluZWNyYWZ0OndoaXRlX3dvb2wECQBuYW1lX2hhc2jRWB7vaIEDiQMKAG5ldHdvcmtfaWSO8paQCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQjAAAACAQAbmFtZRQAbWluZWNyYWZ0OndoaXRlX3dvb2wECQBuYW1lX2hhc2jRWB7vaIEDiQMKAG5ldHdvcmtfaWSO8paQCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:light_gray_wool", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQnAwAACAQAbmFtZRkAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfd29vbAQJAG5hbWVfaGFzaOpdQ1a2v4b3AwoAbmV0d29ya19pZIqZCYEKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQnAwAACAQAbmFtZRkAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfd29vbAQJAG5hbWVfaGFzaOpdQ1a2v4b3AwoAbmV0d29ya19pZIqZCYEKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:gray_wool", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQoAwAACAQAbmFtZRMAbWluZWNyYWZ0OmdyYXlfd29vbAQJAG5hbWVfaGFzaLsc1Lp1xdIOAwoAbmV0d29ya19pZFUs+HgKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQoAwAACAQAbmFtZRMAbWluZWNyYWZ0OmdyYXlfd29vbAQJAG5hbWVfaGFzaLsc1Lp1xdIOAwoAbmV0d29ya19pZFUs+HgKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:black_wool", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQpAwAACAQAbmFtZRQAbWluZWNyYWZ0OmJsYWNrX3dvb2wECQBuYW1lX2hhc2hP2HC6o0X4HAMKAG5ldHdvcmtfaWRUbORcCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQpAwAACAQAbmFtZRQAbWluZWNyYWZ0OmJsYWNrX3dvb2wECQBuYW1lX2hhc2hP2HC6o0X4HAMKAG5ldHdvcmtfaWRUbORcCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:brown_wool", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQqAwAACAQAbmFtZRQAbWluZWNyYWZ0OmJyb3duX3dvb2wECQBuYW1lX2hhc2ig5IW89PrREwMKAG5ldHdvcmtfaWRjT9j8CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQqAwAACAQAbmFtZRQAbWluZWNyYWZ0OmJyb3duX3dvb2wECQBuYW1lX2hhc2ig5IW89PrREwMKAG5ldHdvcmtfaWRjT9j8CgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:red_wool", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQrAwAACAQAbmFtZRIAbWluZWNyYWZ0OnJlZF93b29sBAkAbmFtZV9oYXNoY4TBDq+mFgUDCgBuZXR3b3JrX2lktn9lcAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQrAwAACAQAbmFtZRIAbWluZWNyYWZ0OnJlZF93b29sBAkAbmFtZV9oYXNoY4TBDq+mFgUDCgBuZXR3b3JrX2lktn9lcAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:orange_wool", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAwAACAQAbmFtZRUAbWluZWNyYWZ0Om9yYW5nZV93b29sBAkAbmFtZV9oYXNoFstfrTZfSCgDCgBuZXR3b3JrX2lk+rqywwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAwAACAQAbmFtZRUAbWluZWNyYWZ0Om9yYW5nZV93b29sBAkAbmFtZV9oYXNoFstfrTZfSCgDCgBuZXR3b3JrX2lk+rqywwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:yellow_wool", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQtAwAACAQAbmFtZRUAbWluZWNyYWZ0OnllbGxvd193b29sBAkAbmFtZV9oYXNoTFyus2RHegcDCgBuZXR3b3JrX2lkkKBhXAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQtAwAACAQAbmFtZRUAbWluZWNyYWZ0OnllbGxvd193b29sBAkAbmFtZV9oYXNoTFyus2RHegcDCgBuZXR3b3JrX2lkkKBhXAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:lime_wool", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQuAwAACAQAbmFtZRMAbWluZWNyYWZ0OmxpbWVfd29vbAQJAG5hbWVfaGFzaNVnnzKiMxmeAwoAbmV0d29ya19pZG9b32kKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQuAwAACAQAbmFtZRMAbWluZWNyYWZ0OmxpbWVfd29vbAQJAG5hbWVfaGFzaNVnnzKiMxmeAwoAbmV0d29ya19pZG9b32kKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:green_wool", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQvAwAACAQAbmFtZRQAbWluZWNyYWZ0OmdyZWVuX3dvb2wECQBuYW1lX2hhc2i3mElRYHIcSQMKAG5ldHdvcmtfaWSssprwCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQvAwAACAQAbmFtZRQAbWluZWNyYWZ0OmdyZWVuX3dvb2wECQBuYW1lX2hhc2i3mElRYHIcSQMKAG5ldHdvcmtfaWSssprwCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:cyan_wool", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQwAwAACAQAbmFtZRMAbWluZWNyYWZ0OmN5YW5fd29vbAQJAG5hbWVfaGFzaBNDfvHn8dqFAwoAbmV0d29ya19pZK0hAbgKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQwAwAACAQAbmFtZRMAbWluZWNyYWZ0OmN5YW5fd29vbAQJAG5hbWVfaGFzaBNDfvHn8dqFAwoAbmV0d29ya19pZK0hAbgKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:light_blue_wool", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQxAwAACAQAbmFtZRkAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfd29vbAQJAG5hbWVfaGFzaLWFAUfyxFPNAwoAbmV0d29ya19pZL2oEugKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQxAwAACAQAbmFtZRkAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfd29vbAQJAG5hbWVfaGFzaLWFAUfyxFPNAwoAbmV0d29ya19pZL2oEugKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:blue_wool", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQyAwAACAQAbmFtZRMAbWluZWNyYWZ0OmJsdWVfd29vbAQJAG5hbWVfaGFzaLjHyxxbTWCLAwoAbmV0d29ya19pZPaLdFQKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQyAwAACAQAbmFtZRMAbWluZWNyYWZ0OmJsdWVfd29vbAQJAG5hbWVfaGFzaLjHyxxbTWCLAwoAbmV0d29ya19pZPaLdFQKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:purple_wool", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQzAwAACAQAbmFtZRUAbWluZWNyYWZ0OnB1cnBsZV93b29sBAkAbmFtZV9oYXNojvFtqzjAf/4DCgBuZXR3b3JrX2lklqASNQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQzAwAACAQAbmFtZRUAbWluZWNyYWZ0OnB1cnBsZV93b29sBAkAbmFtZV9oYXNojvFtqzjAf/4DCgBuZXR3b3JrX2lklqASNQoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:magenta_wool", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ0AwAACAQAbmFtZRYAbWluZWNyYWZ0Om1hZ2VudGFfd29vbAQJAG5hbWVfaGFzaGuOHvf+Pd4yAwoAbmV0d29ya19pZI4UoDQKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ0AwAACAQAbmFtZRYAbWluZWNyYWZ0Om1hZ2VudGFfd29vbAQJAG5hbWVfaGFzaGuOHvf+Pd4yAwoAbmV0d29ya19pZI4UoDQKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:pink_wool", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ1AwAACAQAbmFtZRMAbWluZWNyYWZ0OnBpbmtfd29vbAQJAG5hbWVfaGFzaPiVA2pFeoFLAwoAbmV0d29ya19pZOZRO6oKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ1AwAACAQAbmFtZRMAbWluZWNyYWZ0OnBpbmtfd29vbAQJAG5hbWVfaGFzaPiVA2pFeoFLAwoAbmV0d29ya19pZOZRO6oKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:white_carpet", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAAAACAQAbmFtZRYAbWluZWNyYWZ0OndoaXRlX2NhcnBldAQJAG5hbWVfaGFzaNeMHTI1fWPXAwoAbmV0d29ya19pZEahDFcKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAAAACAQAbmFtZRYAbWluZWNyYWZ0OndoaXRlX2NhcnBldAQJAG5hbWVfaGFzaNeMHTI1fWPXAwoAbmV0d29ya19pZEahDFcKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:light_gray_carpet", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRbAwAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY2FycGV0BAkAbmFtZV9oYXNoHPw6ArBAsP0DCgBuZXR3b3JrX2lkQoAeUAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRbAwAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY2FycGV0BAkAbmFtZV9oYXNoHPw6ArBAsP0DCgBuZXR3b3JrX2lkQoAeUAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:gray_carpet", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRaAwAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXlfY2FycGV0BAkAbmFtZV9oYXNoZVR0OI+1VRADCgBuZXR3b3JrX2lkETF4WwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRaAwAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXlfY2FycGV0BAkAbmFtZV9oYXNoZVR0OI+1VRADCgBuZXR3b3JrX2lkETF4WwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:black_carpet", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJsYWNrX2NhcnBldAQJAG5hbWVfaGFzaOk7LP9NptyhAwoAbmV0d29ya19pZFjmXtIKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJsYWNrX2NhcnBldAQJAG5hbWVfaGFzaOk7LP9NptyhAwoAbmV0d29ya19pZFjmXtIKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:brown_carpet", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRfAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJyb3duX2NhcnBldAQJAG5hbWVfaGFzaNaXFyOsAvIvAwoAbmV0d29ya19pZHPjFuoKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRfAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJyb3duX2NhcnBldAQJAG5hbWVfaGFzaNaXFyOsAvIvAwoAbmV0d29ya19pZHPjFuoKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:red_carpet", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAwAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9jYXJwZXQECQBuYW1lX2hhc2i9eSKBf6SO3wMKAG5ldHdvcmtfaWQuhI/KCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAwAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9jYXJwZXQECQBuYW1lX2hhc2i9eSKBf6SO3wMKAG5ldHdvcmtfaWQuhI/KCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:orange_carpet", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRUAwAACAQAbmFtZRcAbWluZWNyYWZ0Om9yYW5nZV9jYXJwZXQECQBuYW1lX2hhc2hIUkO4HlAdygMKAG5ldHdvcmtfaWSyKV9OCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRUAwAACAQAbmFtZRcAbWluZWNyYWZ0Om9yYW5nZV9jYXJwZXQECQBuYW1lX2hhc2hIUkO4HlAdygMKAG5ldHdvcmtfaWSyKV9OCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:yellow_carpet", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRXAwAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19jYXJwZXQECQBuYW1lX2hhc2hSDKX3scCamwMKAG5ldHdvcmtfaWT8nq+ECgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRXAwAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19jYXJwZXQECQBuYW1lX2hhc2hSDKX3scCamwMKAG5ldHdvcmtfaWT8nq+ECgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:lime_carpet", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRYAwAACAQAbmFtZRUAbWluZWNyYWZ0OmxpbWVfY2FycGV0BAkAbmFtZV9oYXNo+6KFOpzsib4DCgBuZXR3b3JrX2lkT+DS4woGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRYAwAACAQAbmFtZRUAbWluZWNyYWZ0OmxpbWVfY2FycGV0BAkAbmFtZV9oYXNo+6KFOpzsib4DCgBuZXR3b3JrX2lkT+DS4woGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:green_carpet", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRgAwAACAQAbmFtZRYAbWluZWNyYWZ0OmdyZWVuX2NhcnBldAQJAG5hbWVfaGFzaCHPMP9ltqFJAwoAbmV0d29ya19pZBgwAvAKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRgAwAACAQAbmFtZRYAbWluZWNyYWZ0OmdyZWVuX2NhcnBldAQJAG5hbWVfaGFzaCHPMP9ltqFJAwoAbmV0d29ya19pZBgwAvAKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:cyan_carpet", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRcAwAACAQAbmFtZRUAbWluZWNyYWZ0OmN5YW5fY2FycGV0BAkAbmFtZV9oYXNobXf62dQBJj8DCgBuZXR3b3JrX2lkKVppLgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRcAwAACAQAbmFtZRUAbWluZWNyYWZ0OmN5YW5fY2FycGV0BAkAbmFtZV9oYXNobXf62dQBJj8DCgBuZXR3b3JrX2lkKVppLgoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:light_blue_carpet", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRWAwAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY2FycGV0BAkAbmFtZV9oYXNo20l4oktdZ3sDCgBuZXR3b3JrX2lkjdeMiwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRWAwAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY2FycGV0BAkAbmFtZV9oYXNo20l4oktdZ3sDCgBuZXR3b3JrX2lkjdeMiwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:blue_carpet", - "block_state_b64": "CgAAAwgAYmxvY2tfaWReAwAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfY2FycGV0BAkAbmFtZV9oYXNo3p3lsW0eQwsDCgBuZXR3b3JrX2lkAovdPQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWReAwAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfY2FycGV0BAkAbmFtZV9oYXNo3p3lsW0eQwsDCgBuZXR3b3JrX2lkAovdPQoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:purple_carpet", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRdAwAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnBsZV9jYXJwZXQECQBuYW1lX2hhc2jwIA9pW/qp7QMKAG5ldHdvcmtfaWTqJqhjCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRdAwAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnBsZV9jYXJwZXQECQBuYW1lX2hhc2jwIA9pW/qp7QMKAG5ldHdvcmtfaWTqJqhjCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:magenta_carpet", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRVAwAACAQAbmFtZRgAbWluZWNyYWZ0Om1hZ2VudGFfY2FycGV0BAkAbmFtZV9oYXNoFXT36YNNZhMDCgBuZXR3b3JrX2lk+tqsGAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRVAwAACAQAbmFtZRgAbWluZWNyYWZ0Om1hZ2VudGFfY2FycGV0BAkAbmFtZV9oYXNoFXT36YNNZhMDCgBuZXR3b3JrX2lk+tqsGAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:pink_carpet", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRZAwAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfY2FycGV0BAkAbmFtZV9oYXNoHll72oqk+OoDCgBuZXR3b3JrX2lkrnBYDwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRZAwAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfY2FycGV0BAkAbmFtZV9oYXNoHll72oqk+OoDCgBuZXR3b3JrX2lkrnBYDwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:white_concrete_powder", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTtAAAACAQAbmFtZR8AbWluZWNyYWZ0OndoaXRlX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaFUk9iXVjwV8AwoAbmV0d29ya19pZJPZY8AKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTtAAAACAQAbmFtZR8AbWluZWNyYWZ0OndoaXRlX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaFUk9iXVjwV8AwoAbmV0d29ya19pZJPZY8AKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:light_gray_concrete_powder", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAwAACAQAbmFtZSQAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNo7EUk30hmUtYDCgBuZXR3b3JrX2lkh8jVIwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAwAACAQAbmFtZSQAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNo7EUk30hmUtYDCgBuZXR3b3JrX2lkh8jVIwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:gray_concrete_powder", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTKAwAACAQAbmFtZR4AbWluZWNyYWZ0OmdyYXlfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoW77af6WihdwDCgBuZXR3b3JrX2lkSsqC1woGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTKAwAACAQAbmFtZR4AbWluZWNyYWZ0OmdyYXlfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoW77af6WihdwDCgBuZXR3b3JrX2lkSsqC1woGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:black_concrete_powder", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTSAwAACAQAbmFtZR8AbWluZWNyYWZ0OmJsYWNrX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaAfWYp0xtgcfAwoAbmV0d29ya19pZMWTC8EKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTSAwAACAQAbmFtZR8AbWluZWNyYWZ0OmJsYWNrX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaAfWYp0xtgcfAwoAbmV0d29ya19pZMWTC8EKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:brown_concrete_powder", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTPAwAACAQAbmFtZR8AbWluZWNyYWZ0OmJyb3duX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaB74EeiLO46XAwoAbmV0d29ya19pZEDHKqwKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTPAwAACAQAbmFtZR8AbWluZWNyYWZ0OmJyb3duX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaB74EeiLO46XAwoAbmV0d29ya19pZEDHKqwKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:red_concrete_powder", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTRAwAACAQAbmFtZR0AbWluZWNyYWZ0OnJlZF9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2gjFut6Z/VH1gMKAG5ldHdvcmtfaWSvcmwYCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTRAwAACAQAbmFtZR0AbWluZWNyYWZ0OnJlZF9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2gjFut6Z/VH1gMKAG5ldHdvcmtfaWSvcmwYCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:orange_concrete_powder", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTEAwAACAQAbmFtZSAAbWluZWNyYWZ0Om9yYW5nZV9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2gADDj2IJiw+gMKAG5ldHdvcmtfaWTHph0FCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTEAwAACAQAbmFtZSAAbWluZWNyYWZ0Om9yYW5nZV9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2gADDj2IJiw+gMKAG5ldHdvcmtfaWTHph0FCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:yellow_concrete_powder", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTHAwAACAQAbmFtZSAAbWluZWNyYWZ0OnllbGxvd19jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2iy6qKNn3ob5wMKAG5ldHdvcmtfaWQZAI39CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTHAwAACAQAbmFtZSAAbWluZWNyYWZ0OnllbGxvd19jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2iy6qKNn3ob5wMKAG5ldHdvcmtfaWQZAI39CgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:lime_concrete_powder", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTIAwAACAQAbmFtZR4AbWluZWNyYWZ0OmxpbWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNo4dYIPslbXPUDCgBuZXR3b3JrX2lk2O8X0AoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTIAwAACAQAbmFtZR4AbWluZWNyYWZ0OmxpbWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNo4dYIPslbXPUDCgBuZXR3b3JrX2lk2O8X0AoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:green_concrete_powder", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTQAwAACAQAbmFtZR8AbWluZWNyYWZ0OmdyZWVuX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaM/c9x2aJh3HAwoAbmV0d29ya19pZA0VfBMKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTQAwAACAQAbmFtZR8AbWluZWNyYWZ0OmdyZWVuX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaM/c9x2aJh3HAwoAbmV0d29ya19pZA0VfBMKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:cyan_concrete_powder", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTMAwAACAQAbmFtZR4AbWluZWNyYWZ0OmN5YW5fY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNok+xKAe7XXjoDCgBuZXR3b3JrX2lkmkn6uwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTMAwAACAQAbmFtZR4AbWluZWNyYWZ0OmN5YW5fY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNok+xKAe7XXjoDCgBuZXR3b3JrX2lkmkn6uwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:light_blue_concrete_powder", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTGAwAACAQAbmFtZSQAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNogScpIQceyAEDCgBuZXR3b3JrX2lkOmVSbgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTGAwAACAQAbmFtZSQAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNogScpIQceyAEDCgBuZXR3b3JrX2lkOmVSbgoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:blue_concrete_powder", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTOAwAACAQAbmFtZR4AbWluZWNyYWZ0OmJsdWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoFp7mmeL86r0DCgBuZXR3b3JrX2lkS3b3RQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTOAwAACAQAbmFtZR4AbWluZWNyYWZ0OmJsdWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoFp7mmeL86r0DCgBuZXR3b3JrX2lkS3b3RQoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:purple_concrete_powder", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTNAwAACAQAbmFtZSAAbWluZWNyYWZ0OnB1cnBsZV9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2iYcVU04hoStwMKAG5ldHdvcmtfaWQXimEjCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTNAwAACAQAbmFtZSAAbWluZWNyYWZ0OnB1cnBsZV9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2iYcVU04hoStwMKAG5ldHdvcmtfaWQXimEjCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:magenta_concrete_powder", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTFAwAACAQAbmFtZSEAbWluZWNyYWZ0Om1hZ2VudGFfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoy/70q6VPsWgDCgBuZXR3b3JrX2lkf9mxQwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTFAwAACAQAbmFtZSEAbWluZWNyYWZ0Om1hZ2VudGFfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoy/70q6VPsWgDCgBuZXR3b3JrX2lkf9mxQwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:pink_concrete_powder", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAwAACAQAbmFtZR4AbWluZWNyYWZ0OnBpbmtfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoVikSAf8DwV0DCgBuZXR3b3JrX2lku2MivwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAwAACAQAbmFtZR4AbWluZWNyYWZ0OnBpbmtfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoVikSAf8DwV0DCgBuZXR3b3JrX2lku2MivwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:white_concrete", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTsAAAACAQAbmFtZRgAbWluZWNyYWZ0OndoaXRlX2NvbmNyZXRlBAkAbmFtZV9oYXNo6zAp7lsLlvkDCgBuZXR3b3JrX2lk3MAYQAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTsAAAACAQAbmFtZRgAbWluZWNyYWZ0OndoaXRlX2NvbmNyZXRlBAkAbmFtZV9oYXNo6zAp7lsLlvkDCgBuZXR3b3JrX2lk3MAYQAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:light_gray_concrete", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR6AwAACAQAbmFtZR0AbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY29uY3JldGUECQBuYW1lX2hhc2hEtet5wuDIKAMKAG5ldHdvcmtfaWQISs02CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR6AwAACAQAbmFtZR0AbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY29uY3JldGUECQBuYW1lX2hhc2hEtet5wuDIKAMKAG5ldHdvcmtfaWQISs02CgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:gray_concrete", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR5AwAACAQAbmFtZRcAbWluZWNyYWZ0OmdyYXlfY29uY3JldGUECQBuYW1lX2hhc2j92INnb0a83AMKAG5ldHdvcmtfaWQj8RHwCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR5AwAACAQAbmFtZRcAbWluZWNyYWZ0OmdyYXlfY29uY3JldGUECQBuYW1lX2hhc2j92INnb0a83AMKAG5ldHdvcmtfaWQj8RHwCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:black_concrete", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAwAACAQAbmFtZRgAbWluZWNyYWZ0OmJsYWNrX2NvbmNyZXRlBAkAbmFtZV9oYXNo2X7NDIQmZ70DCgBuZXR3b3JrX2lk2uiVDQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAwAACAQAbmFtZRgAbWluZWNyYWZ0OmJsYWNrX2NvbmNyZXRlBAkAbmFtZV9oYXNo2X7NDIQmZ70DCgBuZXR3b3JrX2lk2uiVDQoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:brown_concrete", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR+AwAACAQAbmFtZRgAbWluZWNyYWZ0OmJyb3duX2NvbmNyZXRlBAkAbmFtZV9oYXNoeka02BwXf6oDCgBuZXR3b3JrX2lkYf+xDQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR+AwAACAQAbmFtZRgAbWluZWNyYWZ0OmJyb3duX2NvbmNyZXRlBAkAbmFtZV9oYXNoeka02BwXf6oDCgBuZXR3b3JrX2lkYf+xDQoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:red_concrete", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSAAwAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZF9jb25jcmV0ZQQJAG5hbWVfaGFzaPWmNowLGubqAwoAbmV0d29ya19pZKwyx58KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSAAwAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZF9jb25jcmV0ZQQJAG5hbWVfaGFzaPWmNowLGubqAwoAbmV0d29ya19pZKwyx58KBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:orange_concrete", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRzAwAACAQAbmFtZRkAbWluZWNyYWZ0Om9yYW5nZV9jb25jcmV0ZQQJAG5hbWVfaGFzaAgE8XmaAi6+AwoAbmV0d29ya19pZMDQNz8KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRzAwAACAQAbmFtZRkAbWluZWNyYWZ0Om9yYW5nZV9jb25jcmV0ZQQJAG5hbWVfaGFzaAgE8XmaAi6+AwoAbmV0d29ya19pZMDQNz8KBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:yellow_concrete", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR2AwAACAQAbmFtZRkAbWluZWNyYWZ0OnllbGxvd19jb25jcmV0ZQQJAG5hbWVfaGFzaE6ONfJPBd0+AwoAbmV0d29ya19pZMarutwKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR2AwAACAQAbmFtZRkAbWluZWNyYWZ0OnllbGxvd19jb25jcmV0ZQQJAG5hbWVfaGFzaE6ONfJPBd0+AwoAbmV0d29ya19pZMarutwKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:lime_concrete", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR3AwAACAQAbmFtZRcAbWluZWNyYWZ0OmxpbWVfY29uY3JldGUECQBuYW1lX2hhc2gnd8JW6wmJcAMKAG5ldHdvcmtfaWTd47aoCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR3AwAACAQAbmFtZRcAbWluZWNyYWZ0OmxpbWVfY29uY3JldGUECQBuYW1lX2hhc2gnd8JW6wmJcAMKAG5ldHdvcmtfaWTd47aoCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:green_concrete", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR/AwAACAQAbmFtZRgAbWluZWNyYWZ0OmdyZWVuX2NvbmNyZXRlBAkAbmFtZV9oYXNokbFxRKchQZkDCgBuZXR3b3JrX2lkmhZWUgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR/AwAACAQAbmFtZRgAbWluZWNyYWZ0OmdyZWVuX2NvbmNyZXRlBAkAbmFtZV9oYXNokbFxRKchQZkDCgBuZXR3b3JrX2lkmhZWUgoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:cyan_concrete", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR7AwAACAQAbmFtZRcAbWluZWNyYWZ0OmN5YW5fY29uY3JldGUECQBuYW1lX2hhc2hFRrWJ33qj1wMKAG5ldHdvcmtfaWQbi5b8CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR7AwAACAQAbmFtZRcAbWluZWNyYWZ0OmN5YW5fY29uY3JldGUECQBuYW1lX2hhc2hFRrWJ33qj1wMKAG5ldHdvcmtfaWQbi5b8CgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:light_blue_concrete", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR1AwAACAQAbmFtZR0AbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY29uY3JldGUECQBuYW1lX2hhc2gHAe0kl0SE4AMKAG5ldHdvcmtfaWRL/GbSCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR1AwAACAQAbmFtZR0AbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY29uY3JldGUECQBuYW1lX2hhc2gHAe0kl0SE4AMKAG5ldHdvcmtfaWRL/GbSCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:blue_concrete", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR9AwAACAQAbmFtZRcAbWluZWNyYWZ0OmJsdWVfY29uY3JldGUECQBuYW1lX2hhc2hiay301nnj1wMKAG5ldHdvcmtfaWRMvFXNCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR9AwAACAQAbmFtZRcAbWluZWNyYWZ0OmJsdWVfY29uY3JldGUECQBuYW1lX2hhc2hiay301nnj1wMKAG5ldHdvcmtfaWRMvFXNCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:purple_concrete", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR8AwAACAQAbmFtZRkAbWluZWNyYWZ0OnB1cnBsZV9jb25jcmV0ZQQJAG5hbWVfaGFzaHBHflsPIwdXAwoAbmV0d29ya19pZCyKA5gKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR8AwAACAQAbmFtZRkAbWluZWNyYWZ0OnB1cnBsZV9jb25jcmV0ZQQJAG5hbWVfaGFzaHBHflsPIwdXAwoAbmV0d29ya19pZCyKA5gKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:magenta_concrete", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR0AwAACAQAbmFtZRoAbWluZWNyYWZ0Om1hZ2VudGFfY29uY3JldGUECQBuYW1lX2hhc2gN7LuB/OvdZAMKAG5ldHdvcmtfaWTc6ZOdCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR0AwAACAQAbmFtZRoAbWluZWNyYWZ0Om1hZ2VudGFfY29uY3JldGUECQBuYW1lX2hhc2gN7LuB/OvdZAMKAG5ldHdvcmtfaWTc6ZOdCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:pink_concrete", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR4AwAACAQAbmFtZRcAbWluZWNyYWZ0OnBpbmtfY29uY3JldGUECQBuYW1lX2hhc2ii2G5F0u3SOAMKAG5ldHdvcmtfaWSszGgrCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR4AwAACAQAbmFtZRcAbWluZWNyYWZ0OnBpbmtfY29uY3JldGUECQBuYW1lX2hhc2ii2G5F0u3SOAMKAG5ldHdvcmtfaWSszGgrCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:clay", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRSAAAACAQAbmFtZQ4AbWluZWNyYWZ0OmNsYXkECQBuYW1lX2hhc2j/S6sKXRcpzwMKAG5ldHdvcmtfaWRmsb8nCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRSAAAACAQAbmFtZQ4AbWluZWNyYWZ0OmNsYXkECQBuYW1lX2hhc2j/S6sKXRcpzwMKAG5ldHdvcmtfaWRmsb8nCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:hardened_clay", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSsAAAACAQAbmFtZRcAbWluZWNyYWZ0OmhhcmRlbmVkX2NsYXkECQBuYW1lX2hhc2jrnRwCJ0krJAMKAG5ldHdvcmtfaWRBCOrrCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSsAAAACAQAbmFtZRcAbWluZWNyYWZ0OmhhcmRlbmVkX2NsYXkECQBuYW1lX2hhc2jrnRwCJ0krJAMKAG5ldHdvcmtfaWRBCOrrCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:white_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSfAAAACAQAbmFtZRoAbWluZWNyYWZ0OndoaXRlX3RlcnJhY290dGEECQBuYW1lX2hhc2j3RSdgmnAIewMKAG5ldHdvcmtfaWSimKw+CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSfAAAACAQAbmFtZRoAbWluZWNyYWZ0OndoaXRlX3RlcnJhY290dGEECQBuYW1lX2hhc2j3RSdgmnAIewMKAG5ldHdvcmtfaWSimKw+CgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:light_gray_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAwAACAQAbmFtZR8AbWluZWNyYWZ0OmxpZ2h0X2dyYXlfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAz1Ri3wIxomAwoAbmV0d29ya19pZH5qgOcKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAwAACAQAbmFtZR8AbWluZWNyYWZ0OmxpZ2h0X2dyYXlfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAz1Ri3wIxomAwoAbmV0d29ya19pZH5qgOcKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:gray_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTZAwAACAQAbmFtZRkAbWluZWNyYWZ0OmdyYXlfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAXdSLAaNZ9vAwoAbmV0d29ya19pZM1QDV0KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTZAwAACAQAbmFtZRkAbWluZWNyYWZ0OmdyYXlfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAXdSLAaNZ9vAwoAbmV0d29ya19pZM1QDV0KBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:black_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWThAwAACAQAbmFtZRoAbWluZWNyYWZ0OmJsYWNrX3RlcnJhY290dGEECQBuYW1lX2hhc2jxssdv5vlbpgMKAG5ldHdvcmtfaWRE3Ru/CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWThAwAACAQAbmFtZRoAbWluZWNyYWZ0OmJsYWNrX3RlcnJhY290dGEECQBuYW1lX2hhc2jxssdv5vlbpgMKAG5ldHdvcmtfaWRE3Ru/CgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:brown_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTeAwAACAQAbmFtZRoAbWluZWNyYWZ0OmJyb3duX3RlcnJhY290dGEECQBuYW1lX2hhc2gG4kPenmOF9gMKAG5ldHdvcmtfaWQ/i0iNCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTeAwAACAQAbmFtZRoAbWluZWNyYWZ0OmJyb3duX3RlcnJhY290dGEECQBuYW1lX2hhc2gG4kPenmOF9gMKAG5ldHdvcmtfaWQ/i0iNCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:red_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAwAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNo7fX56HXFejEDCgBuZXR3b3JrX2lk8tTF8QoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAwAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNo7fX56HXFejEDCgBuZXR3b3JrX2lk8tTF8QoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:orange_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAwAACAQAbmFtZRsAbWluZWNyYWZ0Om9yYW5nZV90ZXJyYWNvdHRhBAkAbmFtZV9oYXNo0Hjmql3sruMDCgBuZXR3b3JrX2lklmqmkAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAwAACAQAbmFtZRsAbWluZWNyYWZ0Om9yYW5nZV90ZXJyYWNvdHRhBAkAbmFtZV9oYXNo0Hjmql3sruMDCgBuZXR3b3JrX2lklmqmkAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:yellow_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTWAwAACAQAbmFtZRsAbWluZWNyYWZ0OnllbGxvd190ZXJyYWNvdHRhBAkAbmFtZV9oYXNoqkyKKrmA3VcDCgBuZXR3b3JrX2lkaM/orAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTWAwAACAQAbmFtZRsAbWluZWNyYWZ0OnllbGxvd190ZXJyYWNvdHRhBAkAbmFtZV9oYXNoqkyKKrmA3VcDCgBuZXR3b3JrX2lkaM/orAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:lime_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAwAACAQAbmFtZRkAbWluZWNyYWZ0OmxpbWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaANjADFOF9v7AwoAbmV0d29ya19pZJt0XsgKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAwAACAQAbmFtZRkAbWluZWNyYWZ0OmxpbWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaANjADFOF9v7AwoAbmV0d29ya19pZJt0XsgKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:green_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAwAACAQAbmFtZRoAbWluZWNyYWZ0OmdyZWVuX3RlcnJhY290dGEECQBuYW1lX2hhc2j5Ybq36yYwRQMKAG5ldHdvcmtfaWQ8kGdHCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAwAACAQAbmFtZRoAbWluZWNyYWZ0OmdyZWVuX3RlcnJhY290dGEECQBuYW1lX2hhc2j5Ybq36yYwRQMKAG5ldHdvcmtfaWQ8kGdHCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:cyan_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTbAwAACAQAbmFtZRkAbWluZWNyYWZ0OmN5YW5fdGVycmFjb3R0YQQJAG5hbWVfaGFzaN09COzMuHwAAwoAbmV0d29ya19pZIWPCzoKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTbAwAACAQAbmFtZRkAbWluZWNyYWZ0OmN5YW5fdGVycmFjb3R0YQQJAG5hbWVfaGFzaN09COzMuHwAAwoAbmV0d29ya19pZIWPCzoKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:light_blue_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTVAwAACAQAbmFtZR8AbWluZWNyYWZ0OmxpZ2h0X2JsdWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaOMytez7cOZiAwoAbmV0d29ya19pZFHK1UsKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTVAwAACAQAbmFtZR8AbWluZWNyYWZ0OmxpZ2h0X2JsdWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaOMytez7cOZiAwoAbmV0d29ya19pZFHK1UsKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:blue_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAwAACAQAbmFtZRkAbWluZWNyYWZ0OmJsdWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaF6inyTK5RpAAwoAbmV0d29ya19pZF5mVZIKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAwAACAQAbmFtZRkAbWluZWNyYWZ0OmJsdWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaF6inyTK5RpAAwoAbmV0d29ya19pZF5mVZIKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:purple_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAwAACAQAbmFtZRsAbWluZWNyYWZ0OnB1cnBsZV90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoKF7YG61yTbEDCgBuZXR3b3JrX2lkhtRDlwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAwAACAQAbmFtZRsAbWluZWNyYWZ0OnB1cnBsZV90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoKF7YG61yTbEDCgBuZXR3b3JrX2lkhtRDlwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:magenta_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTUAwAACAQAbmFtZRwAbWluZWNyYWZ0Om1hZ2VudGFfdGVycmFjb3R0YQQJAG5hbWVfaGFzaLWvtpAVtztyAwoAbmV0d29ya19pZN5SoakKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTUAwAACAQAbmFtZRwAbWluZWNyYWZ0Om1hZ2VudGFfdGVycmFjb3R0YQQJAG5hbWVfaGFzaLWvtpAVtztyAwoAbmV0d29ya19pZN5SoakKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:pink_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTYAwAACAQAbmFtZRkAbWluZWNyYWZ0OnBpbmtfdGVycmFjb3R0YQQJAG5hbWVfaGFzaJ7mzvyzSQZTAwoAbmV0d29ya19pZDJWe4YKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTYAwAACAQAbmFtZRkAbWluZWNyYWZ0OnBpbmtfdGVycmFjb3R0YQQJAG5hbWVfaGFzaJ7mzvyzSQZTAwoAbmV0d29ya19pZDJWe4YKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:white_glazed_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAAAACAQAbmFtZSEAbWluZWNyYWZ0OndoaXRlX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoiVzCdoHAJo0DCgBuZXR3b3JrX2lkIlj9AAoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAAAACAQAbmFtZSEAbWluZWNyYWZ0OndoaXRlX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoiVzCdoHAJo0DCgBuZXR3b3JrX2lkIlj9AAoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:silver_glazed_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAAAACAQAbmFtZSIAbWluZWNyYWZ0OnNpbHZlcl9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAVsA0CnhzA4AwoAbmV0d29ya19pZPnxtJEKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAAAACAQAbmFtZSIAbWluZWNyYWZ0OnNpbHZlcl9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAVsA0CnhzA4AwoAbmV0d29ya19pZPnxtJEKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:gray_glazed_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAAAACAQAbmFtZSAAbWluZWNyYWZ0OmdyYXlfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2jvLZt9u/lF/AMKAG5ldHdvcmtfaWQVU8eFCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAAAACAQAbmFtZSAAbWluZWNyYWZ0OmdyYXlfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2jvLZt9u/lF/AMKAG5ldHdvcmtfaWQVU8eFCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:black_glazed_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTrAAAACAQAbmFtZSEAbWluZWNyYWZ0OmJsYWNrX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoe8I4xAXbO5UDCgBuZXR3b3JrX2lk2Icb9AoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTrAAAACAQAbmFtZSEAbWluZWNyYWZ0OmJsYWNrX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoe8I4xAXbO5UDCgBuZXR3b3JrX2lk2Icb9AoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:brown_glazed_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWToAAAACAQAbmFtZSEAbWluZWNyYWZ0OmJyb3duX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoSiNZOobbpjoDCgBuZXR3b3JrX2lkJy0jwgoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWToAAAACAQAbmFtZSEAbWluZWNyYWZ0OmJyb3duX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoSiNZOobbpjoDCgBuZXR3b3JrX2lkJy0jwgoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:red_glazed_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTqAAAACAQAbmFtZR8AbWluZWNyYWZ0OnJlZF9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaBdWFGLmCLFVAwoAbmV0d29ya19pZMYBJSEKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTqAAAACAQAbmFtZR8AbWluZWNyYWZ0OnJlZF9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaBdWFGLmCLFVAwoAbmV0d29ya19pZMYBJSEKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:orange_glazed_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAAAACAQAbmFtZSIAbWluZWNyYWZ0Om9yYW5nZV9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaMyJMrnPr7szAwoAbmV0d29ya19pZN6+7TUKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAAAACAQAbmFtZSIAbWluZWNyYWZ0Om9yYW5nZV9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaMyJMrnPr7szAwoAbmV0d29ya19pZN6+7TUKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:yellow_glazed_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAAAACAQAbmFtZSIAbWluZWNyYWZ0OnllbGxvd19nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaN6NaIhf6m0uAwoAbmV0d29ya19pZKRHXeoKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAAAACAQAbmFtZSIAbWluZWNyYWZ0OnllbGxvd19nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaN6NaIhf6m0uAwoAbmV0d29ya19pZKRHXeoKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:lime_glazed_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWThAAAACAQAbmFtZSAAbWluZWNyYWZ0OmxpbWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2iF3E68/rB2EAMKAG5ldHdvcmtfaWSP7qQWCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWThAAAACAQAbmFtZSAAbWluZWNyYWZ0OmxpbWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2iF3E68/rB2EAMKAG5ldHdvcmtfaWSP7qQWCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:green_glazed_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTpAAAACAQAbmFtZSEAbWluZWNyYWZ0OmdyZWVuX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNow5mo8aQDFboDCgBuZXR3b3JrX2lkoF11kgoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTpAAAACAQAbmFtZSEAbWluZWNyYWZ0OmdyZWVuX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNow5mo8aQDFboDCgBuZXR3b3JrX2lkoF11kgoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:cyan_glazed_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAAAACAQAbmFtZSAAbWluZWNyYWZ0OmN5YW5fZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2gnNB+cCFRJhwMKAG5ldHdvcmtfaWT9buMtCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAAAACAQAbmFtZSAAbWluZWNyYWZ0OmN5YW5fZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2gnNB+cCFRJhwMKAG5ldHdvcmtfaWT9buMtCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:light_blue_glazed_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAAAACAQAbmFtZSYAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2gladnCDBKCigMKAG5ldHdvcmtfaWS5CszFCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAAAACAQAbmFtZSYAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2gladnCDBKCigMKAG5ldHdvcmtfaWS5CszFCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:blue_glazed_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTnAAAACAQAbmFtZSAAbWluZWNyYWZ0OmJsdWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2giOZK+2nB1igMKAG5ldHdvcmtfaWR+e22CCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTnAAAACAQAbmFtZSAAbWluZWNyYWZ0OmJsdWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2giOZK+2nB1igMKAG5ldHdvcmtfaWR+e22CCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:purple_glazed_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTbAAAACAQAbmFtZSIAbWluZWNyYWZ0OnB1cnBsZV9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaIQU03txeAfHAwoAbmV0d29ya19pZLKbSE4KBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTbAAAACAQAbmFtZSIAbWluZWNyYWZ0OnB1cnBsZV9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaIQU03txeAfHAwoAbmV0d29ya19pZLKbSE4KBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:magenta_glazed_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTeAAAACAQAbmFtZSMAbWluZWNyYWZ0Om1hZ2VudGFfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2i/SNqDJbfjMgMKAG5ldHdvcmtfaWQKf9UvCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTeAAAACAQAbmFtZSMAbWluZWNyYWZ0Om1hZ2VudGFfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2i/SNqDJbfjMgMKAG5ldHdvcmtfaWQKf9UvCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:pink_glazed_terracotta", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAAAACAQAbmFtZSAAbWluZWNyYWZ0OnBpbmtfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2hik8DVt4g+twMKAG5ldHdvcmtfaWTKzav2CgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAAAACAQAbmFtZSAAbWluZWNyYWZ0OnBpbmtfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2hik8DVt4g+twMKAG5ldHdvcmtfaWTKzav2CgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:purpur_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAAAACAQAbmFtZRYAbWluZWNyYWZ0OnB1cnB1cl9ibG9jawQJAG5hbWVfaGFzaAgLwnUZGlzsAwoAbmV0d29ya19pZLD8ox4KBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQcAZGVmYXVsdAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAAAACAQAbmFtZRYAbWluZWNyYWZ0OnB1cnB1cl9ibG9jawQJAG5hbWVfaGFzaAgLwnUZGlzsAwoAbmV0d29ya19pZLD8ox4KBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQcAZGVmYXVsdAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:purpur_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAAAACAQAbmFtZRYAbWluZWNyYWZ0OnB1cnB1cl9ibG9jawQJAG5hbWVfaGFzaAgLwnUZGlzsAwoAbmV0d29ya19pZPSAFFsKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQUAbGluZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAAAACAQAbmFtZRYAbWluZWNyYWZ0OnB1cnB1cl9ibG9jawQJAG5hbWVfaGFzaAgLwnUZGlzsAwoAbmV0d29ya19pZPSAFFsKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQUAbGluZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:packed_mud", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAgAACAQAbmFtZRQAbWluZWNyYWZ0OnBhY2tlZF9tdWQECQBuYW1lX2hhc2gHOMa121h4FgMKAG5ldHdvcmtfaWTUb6LyCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAgAACAQAbmFtZRQAbWluZWNyYWZ0OnBhY2tlZF9tdWQECQBuYW1lX2hhc2gHOMa121h4FgMKAG5ldHdvcmtfaWTUb6LyCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:mud_bricks", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAgAACAQAbmFtZRQAbWluZWNyYWZ0Om11ZF9icmlja3MECQBuYW1lX2hhc2iDL/SVl/PewQMKAG5ldHdvcmtfaWSkBjaDCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAgAACAQAbmFtZRQAbWluZWNyYWZ0Om11ZF9icmlja3MECQBuYW1lX2hhc2iDL/SVl/PewQMKAG5ldHdvcmtfaWSkBjaDCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:nether_wart_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTWAAAACAQAbmFtZRsAbWluZWNyYWZ0Om5ldGhlcl93YXJ0X2Jsb2NrBAkAbmFtZV9oYXNo9XGS4GNnlV4DCgBuZXR3b3JrX2lkh3apIgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTWAAAACAQAbmFtZRsAbWluZWNyYWZ0Om5ldGhlcl93YXJ0X2Jsb2NrBAkAbmFtZV9oYXNo9XGS4GNnlV4DCgBuZXR3b3JrX2lkh3apIgoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:warped_wart_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAQAACAQAbmFtZRsAbWluZWNyYWZ0OndhcnBlZF93YXJ0X2Jsb2NrBAkAbmFtZV9oYXNo9IqDS9yUPJoDCgBuZXR3b3JrX2lkMpKAbAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAQAACAQAbmFtZRsAbWluZWNyYWZ0OndhcnBlZF93YXJ0X2Jsb2NrBAkAbmFtZV9oYXNo9IqDS9yUPJoDCgBuZXR3b3JrX2lkMpKAbAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:shroomlight", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAQAACAQAbmFtZRUAbWluZWNyYWZ0OnNocm9vbWxpZ2h0BAkAbmFtZV9oYXNoZHCHcHX/HYADCgBuZXR3b3JrX2lkLG2JiwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAQAACAQAbmFtZRUAbWluZWNyYWZ0OnNocm9vbWxpZ2h0BAkAbmFtZV9oYXNoZHCHcHX/HYADCgBuZXR3b3JrX2lkLG2JiwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:crimson_nylium", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTnAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fbnlsaXVtBAkAbmFtZV9oYXNoOr6DJYW2bFYDCgBuZXR3b3JrX2lkuWpRDgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTnAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fbnlsaXVtBAkAbmFtZV9oYXNoOr6DJYW2bFYDCgBuZXR3b3JrX2lkuWpRDgoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:warped_nylium", - "block_state_b64": "CgAAAwgAYmxvY2tfaWToAQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9ueWxpdW0ECQBuYW1lX2hhc2g0Zf89cfr3rwMKAG5ldHdvcmtfaWSu/kekCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWToAQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9ueWxpdW0ECQBuYW1lX2hhc2g0Zf89cfr3rwMKAG5ldHdvcmtfaWSu/kekCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:netherrack", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRXAAAACAQAbmFtZRQAbWluZWNyYWZ0Om5ldGhlcnJhY2sECQBuYW1lX2hhc2i/r5ZyRsvPyQMKAG5ldHdvcmtfaWTAiTOACgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRXAAAACAQAbmFtZRQAbWluZWNyYWZ0Om5ldGhlcnJhY2sECQBuYW1lX2hhc2i/r5ZyRsvPyQMKAG5ldHdvcmtfaWTAiTOACgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:basalt", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTpAQAACAQAbmFtZRAAbWluZWNyYWZ0OmJhc2FsdAQJAG5hbWVfaGFzaH+UQO2yWodiAwoAbmV0d29ya19pZBPNSV4KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTpAQAACAQAbmFtZRAAbWluZWNyYWZ0OmJhc2FsdAQJAG5hbWVfaGFzaH+UQO2yWodiAwoAbmV0d29ya19pZBPNSV4KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:polished_basalt", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTqAQAACAQAbmFtZRkAbWluZWNyYWZ0OnBvbGlzaGVkX2Jhc2FsdAQJAG5hbWVfaGFzaMS+L0gMnRcBAwoAbmV0d29ya19pZF+/mHwKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTqAQAACAQAbmFtZRkAbWluZWNyYWZ0OnBvbGlzaGVkX2Jhc2FsdAQJAG5hbWVfaGFzaMS+L0gMnRcBAwoAbmV0d29ya19pZF+/mHwKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:smooth_basalt", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR4AgAACAQAbmFtZRcAbWluZWNyYWZ0OnNtb290aF9iYXNhbHQECQBuYW1lX2hhc2jKPUdz89kuNAMKAG5ldHdvcmtfaWTkb/oVCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR4AgAACAQAbmFtZRcAbWluZWNyYWZ0OnNtb290aF9iYXNhbHQECQBuYW1lX2hhc2jKPUdz89kuNAMKAG5ldHdvcmtfaWTkb/oVCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:soul_soil", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTrAQAACAQAbmFtZRMAbWluZWNyYWZ0OnNvdWxfc29pbAQJAG5hbWVfaGFzaC1/87ccutuTAwoAbmV0d29ya19pZKc63SMKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTrAQAACAQAbmFtZRMAbWluZWNyYWZ0OnNvdWxfc29pbAQJAG5hbWVfaGFzaC1/87ccutuTAwoAbmV0d29ya19pZKc63SMKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:dirt", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAAAACAQAbmFtZQ4AbWluZWNyYWZ0OmRpcnQECQBuYW1lX2hhc2hXp6jnXAe+kQMKAG5ldHdvcmtfaWQmkQtoCgYAc3RhdGVzCAkAZGlydF90eXBlBgBub3JtYWwAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAAAACAQAbmFtZQ4AbWluZWNyYWZ0OmRpcnQECQBuYW1lX2hhc2hXp6jnXAe+kQMKAG5ldHdvcmtfaWQmkQtoCgYAc3RhdGVzCAkAZGlydF90eXBlBgBub3JtYWwAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:dirt", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAAAACAQAbmFtZQ4AbWluZWNyYWZ0OmRpcnQECQBuYW1lX2hhc2hXp6jnXAe+kQMKAG5ldHdvcmtfaWQId9pLCgYAc3RhdGVzCAkAZGlydF90eXBlBgBjb2Fyc2UAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAAAACAQAbmFtZQ4AbWluZWNyYWZ0OmRpcnQECQBuYW1lX2hhc2hXp6jnXAe+kQMKAG5ldHdvcmtfaWQId9pLCgYAc3RhdGVzCAkAZGlydF90eXBlBgBjb2Fyc2UAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:farmland", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ8AAAACAQAbmFtZRIAbWluZWNyYWZ0OmZhcm1sYW5kBAkAbmFtZV9oYXNoxyQ5ag7LolADCgBuZXR3b3JrX2lkX618FQoGAHN0YXRlcwMSAG1vaXN0dXJpemVkX2Ftb3VudAAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ8AAAACAQAbmFtZRIAbWluZWNyYWZ0OmZhcm1sYW5kBAkAbmFtZV9oYXNoxyQ5ag7LolADCgBuZXR3b3JrX2lkX618FQoGAHN0YXRlcwMSAG1vaXN0dXJpemVkX2Ftb3VudAAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:grass_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAAAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXNzX2Jsb2NrBAkAbmFtZV9oYXNojPyGp3/CSZwDCgBuZXR3b3JrX2lktCgx3goGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAAAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXNzX2Jsb2NrBAkAbmFtZV9oYXNojPyGp3/CSZwDCgBuZXR3b3JrX2lktCgx3goGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:grass_path", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTGAAAACAQAbmFtZRQAbWluZWNyYWZ0OmdyYXNzX3BhdGgECQBuYW1lX2hhc2i0/KZV8Qsy+gMKAG5ldHdvcmtfaWT7CcdzCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTGAAAACAQAbmFtZRQAbWluZWNyYWZ0OmdyYXNzX3BhdGgECQBuYW1lX2hhc2i0/KZV8Qsy+gMKAG5ldHdvcmtfaWT7CcdzCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:podzol", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTzAAAACAQAbmFtZRAAbWluZWNyYWZ0OnBvZHpvbAQJAG5hbWVfaGFzaBzqokRjH4Z1AwoAbmV0d29ya19pZPPS/GUKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTzAAAACAQAbmFtZRAAbWluZWNyYWZ0OnBvZHpvbAQJAG5hbWVfaGFzaBzqokRjH4Z1AwoAbmV0d29ya19pZPPS/GUKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:mycelium", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRuAAAACAQAbmFtZRIAbWluZWNyYWZ0Om15Y2VsaXVtBAkAbmFtZV9oYXNojTN09cKickIDCgBuZXR3b3JrX2lkLNPxXQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRuAAAACAQAbmFtZRIAbWluZWNyYWZ0Om15Y2VsaXVtBAkAbmFtZV9oYXNojTN09cKickIDCgBuZXR3b3JrX2lkLNPxXQoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:mud", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTYAgAACAQAbmFtZQ0AbWluZWNyYWZ0Om11ZAQJAG5hbWVfaGFzaPb/3P+uLy+9AwoAbmV0d29ya19pZPIUlUkKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTYAgAACAQAbmFtZQ0AbWluZWNyYWZ0Om11ZAQJAG5hbWVfaGFzaPb/3P+uLy+9AwoAbmV0d29ya19pZPIUlUkKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:stone", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAAAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lkIQ4xgAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAAAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lkIQ4xgAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:iron_ore", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQPAAAACAQAbmFtZRIAbWluZWNyYWZ0Omlyb25fb3JlBAkAbmFtZV9oYXNoS7BYtLnfx3gDCgBuZXR3b3JrX2lk3loneQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQPAAAACAQAbmFtZRIAbWluZWNyYWZ0Omlyb25fb3JlBAkAbmFtZV9oYXNoS7BYtLnfx3gDCgBuZXR3b3JrX2lk3loneQoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:gold_ore", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQOAAAACAQAbmFtZRIAbWluZWNyYWZ0OmdvbGRfb3JlBAkAbmFtZV9oYXNoC5Y+DUGXLC4DCgBuZXR3b3JrX2lkNhvMfwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQOAAAACAQAbmFtZRIAbWluZWNyYWZ0OmdvbGRfb3JlBAkAbmFtZV9oYXNoC5Y+DUGXLC4DCgBuZXR3b3JrX2lkNhvMfwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:diamond_ore", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ4AAAACAQAbmFtZRUAbWluZWNyYWZ0OmRpYW1vbmRfb3JlBAkAbmFtZV9oYXNokUOJ2wZZrGQDCgBuZXR3b3JrX2lk/dChVAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ4AAAACAQAbmFtZRUAbWluZWNyYWZ0OmRpYW1vbmRfb3JlBAkAbmFtZV9oYXNokUOJ2wZZrGQDCgBuZXR3b3JrX2lk/dChVAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:lapis_ore", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQVAAAACAQAbmFtZRMAbWluZWNyYWZ0OmxhcGlzX29yZQQJAG5hbWVfaGFzaMrmrUrSzb7qAwoAbmV0d29ya19pZMg+qK4KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQVAAAACAQAbmFtZRMAbWluZWNyYWZ0OmxhcGlzX29yZQQJAG5hbWVfaGFzaMrmrUrSzb7qAwoAbmV0d29ya19pZMg+qK4KBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:redstone_ore", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRJAAAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZHN0b25lX29yZQQJAG5hbWVfaGFzaFHVnp8Wc4JbAwoAbmV0d29ya19pZKDYvQoKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRJAAAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZHN0b25lX29yZQQJAG5hbWVfaGFzaFHVnp8Wc4JbAwoAbmV0d29ya19pZKDYvQoKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:coal_ore", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQQAAAACAQAbmFtZRIAbWluZWNyYWZ0OmNvYWxfb3JlBAkAbmFtZV9oYXNo1OjA+Iuy51oDCgBuZXR3b3JrX2lk+R/aKAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQQAAAACAQAbmFtZRIAbWluZWNyYWZ0OmNvYWxfb3JlBAkAbmFtZV9oYXNo1OjA+Iuy51oDCgBuZXR3b3JrX2lk+R/aKAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:copper_ore", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ2AgAACAQAbmFtZRQAbWluZWNyYWZ0OmNvcHBlcl9vcmUECQBuYW1lX2hhc2iSZduSntOzOwMKAG5ldHdvcmtfaWQtIuCnCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ2AgAACAQAbmFtZRQAbWluZWNyYWZ0OmNvcHBlcl9vcmUECQBuYW1lX2hhc2iSZduSntOzOwMKAG5ldHdvcmtfaWQtIuCnCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:emerald_ore", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAAAACAQAbmFtZRUAbWluZWNyYWZ0OmVtZXJhbGRfb3JlBAkAbmFtZV9oYXNoJTovr+VgINsDCgBuZXR3b3JrX2lknbkqCgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAAAACAQAbmFtZRUAbWluZWNyYWZ0OmVtZXJhbGRfb3JlBAkAbmFtZV9oYXNoJTovr+VgINsDCgBuZXR3b3JrX2lknbkqCgoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:quartz_ore", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSZAAAACAQAbmFtZRQAbWluZWNyYWZ0OnF1YXJ0el9vcmUECQBuYW1lX2hhc2g0yNHLMK9TaQMKAG5ldHdvcmtfaWSzN7nzCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSZAAAACAQAbmFtZRQAbWluZWNyYWZ0OnF1YXJ0el9vcmUECQBuYW1lX2hhc2g0yNHLMK9TaQMKAG5ldHdvcmtfaWSzN7nzCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:nether_gold_ore", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQfAgAACAQAbmFtZRkAbWluZWNyYWZ0Om5ldGhlcl9nb2xkX29yZQQJAG5hbWVfaGFzaEJZ7segIBgBAwoAbmV0d29ya19pZNI9pDgKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQfAgAACAQAbmFtZRkAbWluZWNyYWZ0Om5ldGhlcl9nb2xkX29yZQQJAG5hbWVfaGFzaEJZ7segIBgBAwoAbmV0d29ya19pZNI9pDgKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:ancient_debris", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQOAgAACAQAbmFtZRgAbWluZWNyYWZ0OmFuY2llbnRfZGVicmlzBAkAbmFtZV9oYXNoNrbxMc9AwKcDCgBuZXR3b3JrX2lkrSNjEAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQOAgAACAQAbmFtZRgAbWluZWNyYWZ0OmFuY2llbnRfZGVicmlzBAkAbmFtZV9oYXNoNrbxMc9AwKcDCgBuZXR3b3JrX2lkrSNjEAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:deepslate_iron_ore", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSQAgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9pcm9uX29yZQQJAG5hbWVfaGFzaB/fDL9pgvXXAwoAbmV0d29ya19pZFA0bz4KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSQAgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9pcm9uX29yZQQJAG5hbWVfaGFzaB/fDL9pgvXXAwoAbmV0d29ya19pZFA0bz4KBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:deepslate_gold_ore", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9nb2xkX29yZQQJAG5hbWVfaGFzaF9G7WYhKFinAwoAbmV0d29ya19pZHQTfBUKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9nb2xkX29yZQQJAG5hbWVfaGFzaF9G7WYhKFinAwoAbmV0d29ya19pZHQTfBUKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:deepslate_diamond_ore", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSUAgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV9kaWFtb25kX29yZQQJAG5hbWVfaGFzaEUH5USh+iD3AwoAbmV0d29ya19pZHP6VzAKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSUAgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV9kaWFtb25kX29yZQQJAG5hbWVfaGFzaEUH5USh+iD3AwoAbmV0d29ya19pZHP6VzAKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:deepslate_lapis_ore", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV9sYXBpc19vcmUECQBuYW1lX2hhc2j+yFxU/KZs1gMKAG5ldHdvcmtfaWRKINzICgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV9sYXBpc19vcmUECQBuYW1lX2hhc2j+yFxU/KZs1gMKAG5ldHdvcmtfaWRKINzICgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:deepslate_redstone_ore", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSSAgAACAQAbmFtZSAAbWluZWNyYWZ0OmRlZXBzbGF0ZV9yZWRzdG9uZV9vcmUECQBuYW1lX2hhc2iVgM3wWWD6ugMKAG5ldHdvcmtfaWReBdYRCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSSAgAACAQAbmFtZSAAbWluZWNyYWZ0OmRlZXBzbGF0ZV9yZWRzdG9uZV9vcmUECQBuYW1lX2hhc2iVgM3wWWD6ugMKAG5ldHdvcmtfaWReBdYRCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:deepslate_emerald_ore", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSWAgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV9lbWVyYWxkX29yZQQJAG5hbWVfaGFzaNlfo5HTwS6wAwoAbmV0d29ya19pZNeie6sKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSWAgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV9lbWVyYWxkX29yZQQJAG5hbWVfaGFzaNlfo5HTwS6wAwoAbmV0d29ya19pZNeie6sKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:deepslate_coal_ore", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSVAgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9jb2FsX29yZQQJAG5hbWVfaGFzaIjikmcbRrPPAwoAbmV0d29ya19pZD9TiygKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSVAgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9jb2FsX29yZQQJAG5hbWVfaGFzaIjikmcbRrPPAwoAbmV0d29ya19pZD9TiygKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:deepslate_copper_ore", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSXAgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9jb3BwZXJfb3JlBAkAbmFtZV9oYXNottjV4Ev5LAQDCgBuZXR3b3JrX2lkP23rgQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSXAgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9jb3BwZXJfb3JlBAkAbmFtZV9oYXNottjV4Ev5LAQDCgBuZXR3b3JrX2lkP23rgQoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:gravel", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQNAAAACAQAbmFtZRAAbWluZWNyYWZ0OmdyYXZlbAQJAG5hbWVfaGFzaOFxz8XJd2r/AwoAbmV0d29ya19pZBpfI1sKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQNAAAACAQAbmFtZRAAbWluZWNyYWZ0OmdyYXZlbAQJAG5hbWVfaGFzaOFxz8XJd2r/AwoAbmV0d29ya19pZBpfI1sKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:granite", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRNAwAACAQAbmFtZREAbWluZWNyYWZ0OmdyYW5pdGUECQBuYW1lX2hhc2iq+Dur2pw4AwMKAG5ldHdvcmtfaWT2NMfJCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRNAwAACAQAbmFtZREAbWluZWNyYWZ0OmdyYW5pdGUECQBuYW1lX2hhc2iq+Dur2pw4AwMKAG5ldHdvcmtfaWT2NMfJCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:diorite", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRPAwAACAQAbmFtZREAbWluZWNyYWZ0OmRpb3JpdGUECQBuYW1lX2hhc2iaFsq2iinZBQMKAG5ldHdvcmtfaWQqGE6XCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRPAwAACAQAbmFtZREAbWluZWNyYWZ0OmRpb3JpdGUECQBuYW1lX2hhc2iaFsq2iinZBQMKAG5ldHdvcmtfaWQqGE6XCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:andesite", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRRAwAACAQAbmFtZRIAbWluZWNyYWZ0OmFuZGVzaXRlBAkAbmFtZV9oYXNosaLIEnQQoSYDCgBuZXR3b3JrX2lkEApRZAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRRAwAACAQAbmFtZRIAbWluZWNyYWZ0OmFuZGVzaXRlBAkAbmFtZV9oYXNosaLIEnQQoSYDCgBuZXR3b3JrX2lkEApRZAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:blackstone", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQQAgAACAQAbmFtZRQAbWluZWNyYWZ0OmJsYWNrc3RvbmUECQBuYW1lX2hhc2iMFYziD80D6QMKAG5ldHdvcmtfaWSrUryHCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQQAgAACAQAbmFtZRQAbWluZWNyYWZ0OmJsYWNrc3RvbmUECQBuYW1lX2hhc2iMFYziD80D6QMKAG5ldHdvcmtfaWSrUryHCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:deepslate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR5AgAACAQAbmFtZRMAbWluZWNyYWZ0OmRlZXBzbGF0ZQQJAG5hbWVfaGFzaKX5pAblxz8TAwoAbmV0d29ya19pZOJoQjsKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR5AgAACAQAbmFtZRMAbWluZWNyYWZ0OmRlZXBzbGF0ZQQJAG5hbWVfaGFzaKX5pAblxz8TAwoAbmV0d29ya19pZOJoQjsKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:polished_granite", - "block_state_b64": "CgAAAwgAYmxvY2tfaWROAwAACAQAbmFtZRoAbWluZWNyYWZ0OnBvbGlzaGVkX2dyYW5pdGUECQBuYW1lX2hhc2iLiEfys8pFIAMKAG5ldHdvcmtfaWTCxxcHCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWROAwAACAQAbmFtZRoAbWluZWNyYWZ0OnBvbGlzaGVkX2dyYW5pdGUECQBuYW1lX2hhc2iLiEfys8pFIAMKAG5ldHdvcmtfaWTCxxcHCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:polished_diorite", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRQAwAACAQAbmFtZRoAbWluZWNyYWZ0OnBvbGlzaGVkX2Rpb3JpdGUECQBuYW1lX2hhc2hTxY4fKmNmlAMKAG5ldHdvcmtfaWTmtjdRCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRQAwAACAQAbmFtZRoAbWluZWNyYWZ0OnBvbGlzaGVkX2Rpb3JpdGUECQBuYW1lX2hhc2hTxY4fKmNmlAMKAG5ldHdvcmtfaWTmtjdRCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:polished_andesite", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRSAwAACAQAbmFtZRsAbWluZWNyYWZ0OnBvbGlzaGVkX2FuZGVzaXRlBAkAbmFtZV9oYXNovl28uFk4HuQDCgBuZXR3b3JrX2lklFjuCwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRSAwAACAQAbmFtZRsAbWluZWNyYWZ0OnBvbGlzaGVkX2FuZGVzaXRlBAkAbmFtZV9oYXNovl28uFk4HuQDCgBuZXR3b3JrX2lklFjuCwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:polished_blackstone", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQiAgAACAQAbmFtZR0AbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmUECQBuYW1lX2hhc2jT9fHCl6vWQQMKAG5ldHdvcmtfaWR/Ho6oCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQiAgAACAQAbmFtZR0AbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmUECQBuYW1lX2hhc2jT9fHCl6vWQQMKAG5ldHdvcmtfaWR/Ho6oCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:polished_deepslate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR+AgAACAQAbmFtZRwAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaHC1edoaWF3uAwoAbmV0d29ya19pZCPeQsEKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR+AgAACAQAbmFtZRwAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaHC1edoaWF3uAwoAbmV0d29ya19pZCPeQsEKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:sand", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQMAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnNhbmQECQBuYW1lX2hhc2i6lthXXbAyWAMKAG5ldHdvcmtfaWTekU/mCgYAc3RhdGVzCAkAc2FuZF90eXBlBgBub3JtYWwAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQMAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnNhbmQECQBuYW1lX2hhc2i6lthXXbAyWAMKAG5ldHdvcmtfaWTekU/mCgYAc3RhdGVzCAkAc2FuZF90eXBlBgBub3JtYWwAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:sand", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQMAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnNhbmQECQBuYW1lX2hhc2i6lthXXbAyWAMKAG5ldHdvcmtfaWSTgcqmCgYAc3RhdGVzCAkAc2FuZF90eXBlAwByZWQAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQMAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnNhbmQECQBuYW1lX2hhc2i6lthXXbAyWAMKAG5ldHdvcmtfaWSTgcqmCgYAc3RhdGVzCAkAc2FuZF90eXBlAwByZWQAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:cactus", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRRAAAACAQAbmFtZRAAbWluZWNyYWZ0OmNhY3R1cwQJAG5hbWVfaGFzaCG9zL0N4wvGAwoAbmV0d29ya19pZDeCERAKBgBzdGF0ZXMDAwBhZ2UAAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRRAAAACAQAbmFtZRAAbWluZWNyYWZ0OmNhY3R1cwQJAG5hbWVfaGFzaCG9zL0N4wvGAwoAbmV0d29ya19pZDeCERAKBgBzdGF0ZXMDAwBhZ2UAAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:oak_log", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQRAAAACAQAbmFtZREAbWluZWNyYWZ0Om9ha19sb2cECQBuYW1lX2hhc2ho6TS+K7PZFQMKAG5ldHdvcmtfaWQjfjoxCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQRAAAACAQAbmFtZREAbWluZWNyYWZ0Om9ha19sb2cECQBuYW1lX2hhc2ho6TS+K7PZFQMKAG5ldHdvcmtfaWQjfjoxCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:stripped_oak_log", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQJAQAACAQAbmFtZRoAbWluZWNyYWZ0OnN0cmlwcGVkX29ha19sb2cECQBuYW1lX2hhc2h8dqh+OOHU4wMKAG5ldHdvcmtfaWSYKjdrCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQJAQAACAQAbmFtZRoAbWluZWNyYWZ0OnN0cmlwcGVkX29ha19sb2cECQBuYW1lX2hhc2h8dqh+OOHU4wMKAG5ldHdvcmtfaWSYKjdrCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:spruce_log", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ4AwAACAQAbmFtZRQAbWluZWNyYWZ0OnNwcnVjZV9sb2cECQBuYW1lX2hhc2hZ03qaLoF3WgMKAG5ldHdvcmtfaWRlFD8eCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ4AwAACAQAbmFtZRQAbWluZWNyYWZ0OnNwcnVjZV9sb2cECQBuYW1lX2hhc2hZ03qaLoF3WgMKAG5ldHdvcmtfaWRlFD8eCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:stripped_spruce_log", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQEAQAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX3NwcnVjZV9sb2cECQBuYW1lX2hhc2iNrhKjS5IyrgMKAG5ldHdvcmtfaWRQcEC3CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQEAQAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX3NwcnVjZV9sb2cECQBuYW1lX2hhc2iNrhKjS5IyrgMKAG5ldHdvcmtfaWRQcEC3CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:birch_log", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ5AwAACAQAbmFtZRMAbWluZWNyYWZ0OmJpcmNoX2xvZwQJAG5hbWVfaGFzaBUzT3NxsZAnAwoAbmV0d29ya19pZBKN3VQKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ5AwAACAQAbmFtZRMAbWluZWNyYWZ0OmJpcmNoX2xvZwQJAG5hbWVfaGFzaBUzT3NxsZAnAwoAbmV0d29ya19pZBKN3VQKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:stripped_birch_log", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQFAQAACAQAbmFtZRwAbWluZWNyYWZ0OnN0cmlwcGVkX2JpcmNoX2xvZwQJAG5hbWVfaGFzaCFKS4AeuSidAwoAbmV0d29ya19pZN0IONIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQFAQAACAQAbmFtZRwAbWluZWNyYWZ0OnN0cmlwcGVkX2JpcmNoX2xvZwQJAG5hbWVfaGFzaCFKS4AeuSidAwoAbmV0d29ya19pZN0IONIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:jungle_log", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ6AwAACAQAbmFtZRQAbWluZWNyYWZ0Omp1bmdsZV9sb2cECQBuYW1lX2hhc2gkwW0KNulqDgMKAG5ldHdvcmtfaWQaziU/CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ6AwAACAQAbmFtZRQAbWluZWNyYWZ0Omp1bmdsZV9sb2cECQBuYW1lX2hhc2gkwW0KNulqDgMKAG5ldHdvcmtfaWQaziU/CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:stripped_jungle_log", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAQAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2p1bmdsZV9sb2cECQBuYW1lX2hhc2hAwMsgOk02JAMKAG5ldHdvcmtfaWQvls0eCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAQAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2p1bmdsZV9sb2cECQBuYW1lX2hhc2hAwMsgOk02JAMKAG5ldHdvcmtfaWQvls0eCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:acacia_log", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAAAACAQAbmFtZRQAbWluZWNyYWZ0OmFjYWNpYV9sb2cECQBuYW1lX2hhc2iV48VpYhjoYQMKAG5ldHdvcmtfaWRxEqe0CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAAAACAQAbmFtZRQAbWluZWNyYWZ0OmFjYWNpYV9sb2cECQBuYW1lX2hhc2iV48VpYhjoYQMKAG5ldHdvcmtfaWRxEqe0CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:stripped_acacia_log", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAQAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2FjYWNpYV9sb2cECQBuYW1lX2hhc2hJb0lQqnEqlgMKAG5ldHdvcmtfaWRg3IdRCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAQAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2FjYWNpYV9sb2cECQBuYW1lX2hhc2hJb0lQqnEqlgMKAG5ldHdvcmtfaWRg3IdRCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:dark_oak_log", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ7AwAACAQAbmFtZRYAbWluZWNyYWZ0OmRhcmtfb2FrX2xvZwQJAG5hbWVfaGFzaIWfVRd0XUo3AwoAbmV0d29ya19pZPMM7LYKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ7AwAACAQAbmFtZRYAbWluZWNyYWZ0OmRhcmtfb2FrX2xvZwQJAG5hbWVfaGFzaIWfVRd0XUo3AwoAbmV0d29ya19pZPMM7LYKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:stripped_dark_oak_log", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQIAQAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2Rhcmtfb2FrX2xvZwQJAG5hbWVfaGFzaPFTdxRdPwkOAwoAbmV0d29ya19pZDIzenIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQIAQAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2Rhcmtfb2FrX2xvZwQJAG5hbWVfaGFzaPFTdxRdPwkOAwoAbmV0d29ya19pZDIzenIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:mangrove_log", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAgAACAQAbmFtZRYAbWluZWNyYWZ0Om1hbmdyb3ZlX2xvZwQJAG5hbWVfaGFzaHZe6DzPZBobAwoAbmV0d29ya19pZG6DuYkKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAgAACAQAbmFtZRYAbWluZWNyYWZ0Om1hbmdyb3ZlX2xvZwQJAG5hbWVfaGFzaHZe6DzPZBobAwoAbmV0d29ya19pZG6DuYkKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:stripped_mangrove_log", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX21hbmdyb3ZlX2xvZwQJAG5hbWVfaGFzaLqIBo4hwA//AwoAbmV0d29ya19pZPtRn7UKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX21hbmdyb3ZlX2xvZwQJAG5hbWVfaGFzaLqIBo4hwA//AwoAbmV0d29ya19pZPtRn7UKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:cherry_log", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQXAwAACAQAbmFtZRQAbWluZWNyYWZ0OmNoZXJyeV9sb2cECQBuYW1lX2hhc2hwFlaioppB1wMKAG5ldHdvcmtfaWS2sdXECgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQXAwAACAQAbmFtZRQAbWluZWNyYWZ0OmNoZXJyeV9sb2cECQBuYW1lX2hhc2hwFlaioppB1wMKAG5ldHdvcmtfaWS2sdXECgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:stripped_cherry_log", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQWAwAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2NoZXJyeV9sb2cECQBuYW1lX2hhc2i85H6G+WhXaAMKAG5ldHdvcmtfaWRjzoglCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQWAwAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2NoZXJyeV9sb2cECQBuYW1lX2hhc2i85H6G+WhXaAMKAG5ldHdvcmtfaWRjzoglCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:crimson_stem", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAQAACAQAbmFtZRYAbWluZWNyYWZ0OmNyaW1zb25fc3RlbQQJAG5hbWVfaGFzaM0FzfL0UTKZAwoAbmV0d29ya19pZKvzID0KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAQAACAQAbmFtZRYAbWluZWNyYWZ0OmNyaW1zb25fc3RlbQQJAG5hbWVfaGFzaM0FzfL0UTKZAwoAbmV0d29ya19pZKvzID0KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:stripped_crimson_stem", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTvAQAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2NyaW1zb25fc3RlbQQJAG5hbWVfaGFzaDlA6nood57EAwoAbmV0d29ya19pZHrIqjIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTvAQAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2NyaW1zb25fc3RlbQQJAG5hbWVfaGFzaDlA6nood57EAwoAbmV0d29ya19pZHrIqjIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:warped_stem", - "block_state_b64": "CgAAAwgAYmxvY2tfaWThAQAACAQAbmFtZRUAbWluZWNyYWZ0OndhcnBlZF9zdGVtBAkAbmFtZV9oYXNon7cKfPZxdrUDCgBuZXR3b3JrX2lkerWyMwoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWThAQAACAQAbmFtZRUAbWluZWNyYWZ0OndhcnBlZF9zdGVtBAkAbmFtZV9oYXNon7cKfPZxdrUDCgBuZXR3b3JrX2lkerWyMwoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:stripped_warped_stem", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTwAQAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX3dhcnBlZF9zdGVtBAkAbmFtZV9oYXNoEw+y0dDPSd8DCgBuZXR3b3JrX2lkIQ9vBAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTwAQAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX3dhcnBlZF9zdGVtBAkAbmFtZV9oYXNoEw+y0dDPSd8DCgBuZXR3b3JrX2lkIQ9vBAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:oak_wood", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAQAACAQAbmFtZRIAbWluZWNyYWZ0Om9ha193b29kBAkAbmFtZV9oYXNoqQIkuVPyJX0DCgBuZXR3b3JrX2lku2G1YAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAQAACAQAbmFtZRIAbWluZWNyYWZ0Om9ha193b29kBAkAbmFtZV9oYXNoqQIkuVPyJX0DCgBuZXR3b3JrX2lku2G1YAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:spruce_wood", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQtBAAACAQAbmFtZRUAbWluZWNyYWZ0OnNwcnVjZV93b29kBAkAbmFtZV9oYXNoTrIJ5TAQ+OgDCgBuZXR3b3JrX2lkaXLxCwoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQtBAAACAQAbmFtZRUAbWluZWNyYWZ0OnNwcnVjZV93b29kBAkAbmFtZV9oYXNoTrIJ5TAQ+OgDCgBuZXR3b3JrX2lkaXLxCwoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:birch_wood", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQuBAAACAQAbmFtZRQAbWluZWNyYWZ0OmJpcmNoX3dvb2QECQBuYW1lX2hhc2iqVjG4xt0cKQMKAG5ldHdvcmtfaWS06c5VCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQuBAAACAQAbmFtZRQAbWluZWNyYWZ0OmJpcmNoX3dvb2QECQBuYW1lX2hhc2iqVjG4xt0cKQMKAG5ldHdvcmtfaWS06c5VCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:jungle_wood", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQvBAAACAQAbmFtZRUAbWluZWNyYWZ0Omp1bmdsZV93b29kBAkAbmFtZV9oYXNo9bYW29ORWCoDCgBuZXR3b3JrX2lkyFyKLQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQvBAAACAQAbmFtZRUAbWluZWNyYWZ0Omp1bmdsZV93b29kBAkAbmFtZV9oYXNo9bYW29ORWCoDCgBuZXR3b3JrX2lkyFyKLQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:acacia_wood", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQwBAAACAQAbmFtZRUAbWluZWNyYWZ0OmFjYWNpYV93b29kBAkAbmFtZV9oYXNoKkDfgzlJUcIDCgBuZXR3b3JrX2lkuTWlcgoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQwBAAACAQAbmFtZRUAbWluZWNyYWZ0OmFjYWNpYV93b29kBAkAbmFtZV9oYXNoKkDfgzlJUcIDCgBuZXR3b3JrX2lkuTWlcgoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:dark_oak_wood", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQxBAAACAQAbmFtZRcAbWluZWNyYWZ0OmRhcmtfb2FrX3dvb2QECQBuYW1lX2hhc2jaKv4ORLadAAMKAG5ldHdvcmtfaWSDrNQ8CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQxBAAACAQAbmFtZRcAbWluZWNyYWZ0OmRhcmtfb2FrX3dvb2QECQBuYW1lX2hhc2jaKv4ORLadAAMKAG5ldHdvcmtfaWSDrNQ8CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:stripped_oak_wood", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQyBAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0cmlwcGVkX29ha193b29kBAkAbmFtZV9oYXNovW6KCv+VZnsDCgBuZXR3b3JrX2lkkhWGegoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQyBAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0cmlwcGVkX29ha193b29kBAkAbmFtZV9oYXNovW6KCv+VZnsDCgBuZXR3b3JrX2lkkhWGegoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:stripped_spruce_wood", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQzBAAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX3NwcnVjZV93b29kBAkAbmFtZV9oYXNoMnuUk4Xo6icDCgBuZXR3b3JrX2lkes2ydAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQzBAAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX3NwcnVjZV93b29kBAkAbmFtZV9oYXNoMnuUk4Xo6icDCgBuZXR3b3JrX2lkes2ydAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:stripped_birch_wood", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ0BAAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2JpcmNoX3dvb2QECQBuYW1lX2hhc2hm88R604TKbAMKAG5ldHdvcmtfaWRleEMJCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ0BAAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2JpcmNoX3dvb2QECQBuYW1lX2hhc2hm88R604TKbAMKAG5ldHdvcmtfaWRleEMJCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:stripped_jungle_wood", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ1BAAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX2p1bmdsZV93b29kBAkAbmFtZV9oYXNoUVs6KsZQRBoDCgBuZXR3b3JrX2lk92k8HQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ1BAAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX2p1bmdsZV93b29kBAkAbmFtZV9oYXNoUVs6KsZQRBoDCgBuZXR3b3JrX2lk92k8HQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:stripped_acacia_wood", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ2BAAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX2FjYWNpYV93b29kBAkAbmFtZV9oYXNo/kOPN2bCJhUDCgBuZXR3b3JrX2lktl6LwQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ2BAAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX2FjYWNpYV93b29kBAkAbmFtZV9oYXNo/kOPN2bCJhUDCgBuZXR3b3JrX2lktl6LwQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:stripped_dark_oak_wood", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ3BAAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX2Rhcmtfb2FrX3dvb2QECQBuYW1lX2hhc2h2jFDfKVFgfAMKAG5ldHdvcmtfaWTgZQ5VCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ3BAAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX2Rhcmtfb2FrX3dvb2QECQBuYW1lX2hhc2h2jFDfKVFgfAMKAG5ldHdvcmtfaWTgZQ5VCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:mangrove_wood", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTwAgAACAQAbmFtZRcAbWluZWNyYWZ0Om1hbmdyb3ZlX3dvb2QECQBuYW1lX2hhc2iXVxG0JG2fVAMKAG5ldHdvcmtfaWTok1JCCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTwAgAACAQAbmFtZRcAbWluZWNyYWZ0Om1hbmdyb3ZlX3dvb2QECQBuYW1lX2hhc2iXVxG0JG2fVAMKAG5ldHdvcmtfaWTok1JCCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:stripped_mangrove_wood", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTxAgAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX21hbmdyb3ZlX3dvb2QECQBuYW1lX2hhc2h7CkbaBF7/WAMKAG5ldHdvcmtfaWQLAX88CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTxAgAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX21hbmdyb3ZlX3dvb2QECQBuYW1lX2hhc2h7CkbaBF7/WAMKAG5ldHdvcmtfaWQLAX88CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:cherry_wood", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQhAwAACAQAbmFtZRUAbWluZWNyYWZ0OmNoZXJyeV93b29kBAkAbmFtZV9oYXNoAW8srlmpBM8DCgBuZXR3b3JrX2lkEALMfAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AQwAc3RyaXBwZWRfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQhAwAACAQAbmFtZRUAbWluZWNyYWZ0OmNoZXJyeV93b29kBAkAbmFtZV9oYXNoAW8srlmpBM8DCgBuZXR3b3JrX2lkEALMfAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AQwAc3RyaXBwZWRfYml0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:stripped_cherry_wood", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQgAwAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX2NoZXJyeV93b29kBAkAbmFtZV9oYXNo/e7KXv+CB38DCgBuZXR3b3JrX2lkg5aVtQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQgAwAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX2NoZXJyeV93b29kBAkAbmFtZV9oYXNo/e7KXv+CB38DCgBuZXR3b3JrX2lkg5aVtQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:crimson_hyphae", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQqAgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25faHlwaGFlBAkAbmFtZV9oYXNouRmKmfSqEWADCgBuZXR3b3JrX2lk+Tm5rQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQqAgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25faHlwaGFlBAkAbmFtZV9oYXNouRmKmfSqEWADCgBuZXR3b3JrX2lk+Tm5rQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:stripped_crimson_hyphae", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQrAgAACAQAbmFtZSEAbWluZWNyYWZ0OnN0cmlwcGVkX2NyaW1zb25faHlwaGFlBAkAbmFtZV9oYXNoFffwmABq4LUDCgBuZXR3b3JrX2lkZAlUbgoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQrAgAACAQAbmFtZSEAbWluZWNyYWZ0OnN0cmlwcGVkX2NyaW1zb25faHlwaGFlBAkAbmFtZV9oYXNoFffwmABq4LUDCgBuZXR3b3JrX2lkZAlUbgoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:warped_hyphae", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQpAgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9oeXBoYWUECQBuYW1lX2hhc2hn8plQUr6pmQMKAG5ldHdvcmtfaWRU2AIBCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQpAgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9oeXBoYWUECQBuYW1lX2hhc2hn8plQUr6pmQMKAG5ldHdvcmtfaWRU2AIBCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:stripped_warped_hyphae", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAgAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX3dhcnBlZF9oeXBoYWUECQBuYW1lX2hhc2irKq+HYPSgjQMKAG5ldHdvcmtfaWSbrOPDCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAgAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX3dhcnBlZF9oeXBoYWUECQBuYW1lX2hhc2irKq+HYPSgjQMKAG5ldHdvcmtfaWSbrOPDCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:bamboo_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQOAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJhbWJvb19ibG9jawQJAG5hbWVfaGFzaAbDeur6stIBAwoAbmV0d29ya19pZCJAwn0KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQOAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJhbWJvb19ibG9jawQJAG5hbWVfaGFzaAbDeur6stIBAwoAbmV0d29ya19pZCJAwn0KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:stripped_bamboo_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQPAwAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2JhbWJvb19ibG9jawQJAG5hbWVfaGFzaJpwytpZOZM9AwoAbmV0d29ya19pZKuRbNEKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQPAwAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2JhbWJvb19ibG9jawQJAG5hbWVfaGFzaJpwytpZOZM9AwoAbmV0d29ya19pZKuRbNEKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:oak_leaves", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQSAAAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19sZWF2ZXMECQBuYW1lX2hhc2h6O4xGqA2oKgMKAG5ldHdvcmtfaWT98c59CgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQSAAAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19sZWF2ZXMECQBuYW1lX2hhc2h6O4xGqA2oKgMKAG5ldHdvcmtfaWT98c59CgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:spruce_leaves", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQfBAAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9sZWF2ZXMECQBuYW1lX2hhc2i9x1CtNAuqZwMKAG5ldHdvcmtfaWSzF7pTCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQfBAAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9sZWF2ZXMECQBuYW1lX2hhc2i9x1CtNAuqZwMKAG5ldHdvcmtfaWSzF7pTCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:birch_leaves", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQgBAAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX2xlYXZlcwQJAG5hbWVfaGFzaBlAGHaoaLZSAwoAbmV0d29ya19pZOjtvWcKBgBzdGF0ZXMBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQgBAAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX2xlYXZlcwQJAG5hbWVfaGFzaBlAGHaoaLZSAwoAbmV0d29ya19pZOjtvWcKBgBzdGF0ZXMBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:jungle_leaves", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQhBAAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9sZWF2ZXMECQBuYW1lX2hhc2iW1uAH07zGhgMKAG5ldHdvcmtfaWSA5KX0CgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQhBAAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9sZWF2ZXMECQBuYW1lX2hhc2iW1uAH07zGhgMKAG5ldHdvcmtfaWSA5KX0CgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:acacia_leaves", - "block_state_b64": "CgAAAwgAYmxvY2tfaWShAAAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9sZWF2ZXMECQBuYW1lX2hhc2iZJf8dAgDRNQMKAG5ldHdvcmtfaWQ/G7VuCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAAAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9sZWF2ZXMECQBuYW1lX2hhc2iZJf8dAgDRNQMKAG5ldHdvcmtfaWQ/G7VuCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:dark_oak_leaves", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQiBAAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX2xlYXZlcwQJAG5hbWVfaGFzaCk7rDipWFSjAwoAbmV0d29ya19pZJ2AkbYKBgBzdGF0ZXMBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQiBAAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX2xlYXZlcwQJAG5hbWVfaGFzaCk7rDipWFSjAwoAbmV0d29ya19pZJ2AkbYKBgBzdGF0ZXMBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:mangrove_leaves", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX2xlYXZlcwQJAG5hbWVfaGFzaKyI/dWvhEG8AwoAbmV0d29ya19pZPQxCZ8KBgBzdGF0ZXMBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX2xlYXZlcwQJAG5hbWVfaGFzaKyI/dWvhEG8AwoAbmV0d29ya19pZPQxCZ8KBgBzdGF0ZXMBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:cherry_leaves", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQjAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9sZWF2ZXMECQBuYW1lX2hhc2giTs9ChhYBlQMKAG5ldHdvcmtfaWR8bPpwCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQjAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9sZWF2ZXMECQBuYW1lX2hhc2giTs9ChhYBlQMKAG5ldHdvcmtfaWR8bPpwCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:azalea_leaves", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRDAgAACAQAbmFtZRcAbWluZWNyYWZ0OmF6YWxlYV9sZWF2ZXMECQBuYW1lX2hhc2iXFhD57wFS7AMKAG5ldHdvcmtfaWTNB/9ECgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRDAgAACAQAbmFtZRcAbWluZWNyYWZ0OmF6YWxlYV9sZWF2ZXMECQBuYW1lX2hhc2iXFhD57wFS7AMKAG5ldHdvcmtfaWTNB/9ECgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:azalea_leaves_flowered", - "block_state_b64": "CgAAAwgAYmxvY2tfaWREAgAACAQAbmFtZSAAbWluZWNyYWZ0OmF6YWxlYV9sZWF2ZXNfZmxvd2VyZWQECQBuYW1lX2hhc2gs8jxlS/pMrwMKAG5ldHdvcmtfaWQ7W4PyCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWREAgAACAQAbmFtZSAAbWluZWNyYWZ0OmF6YWxlYV9sZWF2ZXNfZmxvd2VyZWQECQBuYW1lX2hhc2gs8jxlS/pMrwMKAG5ldHdvcmtfaWQ7W4PyCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { - "id": "minecraft:sapling", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAAAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWQmoOEvCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUDAG9hawADBwB2ZXJzaW9uBEYUAQA=" + "id": "minecraft:oak_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAAAACAQAbmFtZRUAbWluZWNyYWZ0Om9ha19zYXBsaW5nBAkAbmFtZV9oYXNoogXcT9QfjiUDCgBuZXR3b3JrX2lkG22C+AoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24DABUBAA==" }, { - "id": "minecraft:sapling", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAAAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWQO8pAmCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUGAHNwcnVjZQADBwB2ZXJzaW9uBEYUAQA=" + "id": "minecraft:spruce_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ4BAAACAQAbmFtZRgAbWluZWNyYWZ0OnNwcnVjZV9zYXBsaW5nBAkAbmFtZV9oYXNoe8hz4uYP0FcDCgBuZXR3b3JrX2lkUQmhaQoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24DABUBAA==" }, { - "id": "minecraft:sapling", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAAAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWQDHhokCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUFAGJpcmNoAAMHAHZlcnNpb24ERhQBAA==" + "id": "minecraft:birch_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ5BAAACAQAbmFtZRcAbWluZWNyYWZ0OmJpcmNoX3NhcGxpbmcECQBuYW1lX2hhc2h348iJQ/tK4wMKAG5ldHdvcmtfaWQ2Uh53CgYAc3RhdGVzAQcAYWdlX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { - "id": "minecraft:sapling", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAAAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWTdQrcyCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUGAGp1bmdsZQADBwB2ZXJzaW9uBEYUAQA=" + "id": "minecraft:jungle_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ6BAAACAQAbmFtZRgAbWluZWNyYWZ0Omp1bmdsZV9zYXBsaW5nBAkAbmFtZV9oYXNo7tyTOdSrxaADCgBuZXR3b3JrX2lkXmBAdAoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24DABUBAA==" }, { - "id": "minecraft:sapling", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAAAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWRCDffNCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUGAGFjYWNpYQADBwB2ZXJzaW9uBEYUAQA=" + "id": "minecraft:acacia_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ7BAAACAQAbmFtZRgAbWluZWNyYWZ0OmFjYWNpYV9zYXBsaW5nBAkAbmFtZV9oYXNo99sg15uoX7ADCgBuZXR3b3JrX2lkPXX1KgoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24DABUBAA==" }, { - "id": "minecraft:sapling", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAAAACAQAbmFtZREAbWluZWNyYWZ0OnNhcGxpbmcECQBuYW1lX2hhc2goZxi1oICLKwMKAG5ldHdvcmtfaWR0BRzPCgYAc3RhdGVzAQcAYWdlX2JpdAAIDABzYXBsaW5nX3R5cGUIAGRhcmtfb2FrAAMHAHZlcnNpb24ERhQBAA==" + "id": "minecraft:dark_oak_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ8BAAACAQAbmFtZRoAbWluZWNyYWZ0OmRhcmtfb2FrX3NhcGxpbmcECQBuYW1lX2hhc2jnVzFplW7cHgMKAG5ldHdvcmtfaWTD4giHCgYAc3RhdGVzAQcAYWdlX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:mangrove_propagule", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTZAgAACAQAbmFtZRwAbWluZWNyYWZ0Om1hbmdyb3ZlX3Byb3BhZ3VsZQQJAG5hbWVfaGFzaJGeox6hkfLFAwoAbmV0d29ya19pZAIpvpYKBgBzdGF0ZXMBBwBoYW5naW5nAAMPAHByb3BhZ3VsZV9zdGFnZQAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTZAgAACAQAbmFtZRwAbWluZWNyYWZ0Om1hbmdyb3ZlX3Byb3BhZ3VsZQQJAG5hbWVfaGFzaJGeox6hkfLFAwoAbmV0d29ya19pZAIpvpYKBgBzdGF0ZXMBBwBoYW5naW5nAAMPAHByb3BhZ3VsZV9zdGFnZQAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:cherry_sapling", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQiAwAACAQAbmFtZRgAbWluZWNyYWZ0OmNoZXJyeV9zYXBsaW5nBAkAbmFtZV9oYXNoGrPpNMf1LtcDCgBuZXR3b3JrX2lkypakXQoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQiAwAACAQAbmFtZRgAbWluZWNyYWZ0OmNoZXJyeV9zYXBsaW5nBAkAbmFtZV9oYXNoGrPpNMf1LtcDCgBuZXR3b3JrX2lkypakXQoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:bee_nest", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTZAQAACAQAbmFtZRIAbWluZWNyYWZ0OmJlZV9uZXN0BAkAbmFtZV9oYXNo2R2WBxUHEZIDCgBuZXR3b3JrX2lkiXWLEAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAADCwBob25leV9sZXZlbAAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTZAQAACAQAbmFtZRIAbWluZWNyYWZ0OmJlZV9uZXN0BAkAbmFtZV9oYXNo2R2WBxUHEZIDCgBuZXR3b3JrX2lkiXWLEAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAADCwBob25leV9sZXZlbAAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:wheat_seeds" @@ -2095,7 +2247,7 @@ }, { "id": "minecraft:melon_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRnAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1lbG9uX2Jsb2NrBAkAbmFtZV9oYXNoXxSm0iYpAx8DCgBuZXR3b3JrX2lkC9rqygoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRnAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1lbG9uX2Jsb2NrBAkAbmFtZV9oYXNoXxSm0iYpAx8DCgBuZXR3b3JrX2lkC9rqygoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:melon_slice" @@ -2111,205 +2263,205 @@ }, { "id": "minecraft:pumpkin", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRWAAAACAQAbmFtZREAbWluZWNyYWZ0OnB1bXBraW4ECQBuYW1lX2hhc2gc8A3jaSzWbgMKAG5ldHdvcmtfaWRFGA+xCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRWAAAACAQAbmFtZREAbWluZWNyYWZ0OnB1bXBraW4ECQBuYW1lX2hhc2gc8A3jaSzWbgMKAG5ldHdvcmtfaWRFGA+xCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:carved_pumpkin", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSaAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNhcnZlZF9wdW1wa2luBAkAbmFtZV9oYXNoPu1T0MJuG90DCgBuZXR3b3JrX2lkXNNn5QoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSaAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNhcnZlZF9wdW1wa2luBAkAbmFtZV9oYXNoPu1T0MJuG90DCgBuZXR3b3JrX2lkXNNn5QoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:lit_pumpkin", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRbAAAACAQAbmFtZRUAbWluZWNyYWZ0OmxpdF9wdW1wa2luBAkAbmFtZV9oYXNo7gWtEm2uPL0DCgBuZXR3b3JrX2lki8sU4AoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRbAAAACAQAbmFtZRUAbWluZWNyYWZ0OmxpdF9wdW1wa2luBAkAbmFtZV9oYXNo7gWtEm2uPL0DCgBuZXR3b3JrX2lki8sU4AoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:honeycomb" }, { - "id": "minecraft:tallgrass", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQfAAAACAQAbmFtZRMAbWluZWNyYWZ0OnRhbGxncmFzcwQJAG5hbWVfaGFzaC3PXpAXXYswAwoAbmV0d29ya19pZOh33DMKBgBzdGF0ZXMIDwB0YWxsX2dyYXNzX3R5cGUEAGZlcm4AAwcAdmVyc2lvbgRGFAEA" + "id": "minecraft:fern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRPBAAACAQAbmFtZQ4AbWluZWNyYWZ0OmZlcm4ECQBuYW1lX2hhc2iHbj3yXFn4owMKAG5ldHdvcmtfaWQKC6u7CgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { - "id": "minecraft:double_plant", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZMx1sfgKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQQAZmVybgEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "id": "minecraft:large_fern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRgBAAACAQAbmFtZRQAbWluZWNyYWZ0OmxhcmdlX2Zlcm4ECQBuYW1lX2hhc2gnE9sd0LzHtQMKAG5ldHdvcmtfaWTS9hG4CgYAc3RhdGVzAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uAwAVAQA=" }, { - "id": "minecraft:tallgrass", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQfAAAACAQAbmFtZRMAbWluZWNyYWZ0OnRhbGxncmFzcwQJAG5hbWVfaGFzaC3PXpAXXYswAwoAbmV0d29ya19pZErptfIKBgBzdGF0ZXMIDwB0YWxsX2dyYXNzX3R5cGUEAHRhbGwAAwcAdmVyc2lvbgRGFAEA" + "id": "minecraft:short_grass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQfAAAACAQAbmFtZRUAbWluZWNyYWZ0OnNob3J0X2dyYXNzBAkAbmFtZV9oYXNobWQghLH0bLcDCgBuZXR3b3JrX2lkJWOOqAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { - "id": "minecraft:double_plant", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZAbadmIKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQUAZ3Jhc3MBDwB1cHBlcl9ibG9ja19iaXQAAAMHAHZlcnNpb24ERhQBAA==" + "id": "minecraft:tall_grass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRfBAAACAQAbmFtZRQAbWluZWNyYWZ0OnRhbGxfZ3Jhc3MECQBuYW1lX2hhc2ii5MyZJpv4sgMKAG5ldHdvcmtfaWRRfeH4CgYAc3RhdGVzAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:nether_sprouts" }, { "id": "minecraft:fire_coral", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRGAwAACAQAbmFtZRQAbWluZWNyYWZ0OmZpcmVfY29yYWwECQBuYW1lX2hhc2hOHyyECVQVJwMKAG5ldHdvcmtfaWS9vF0UCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRGAwAACAQAbmFtZRQAbWluZWNyYWZ0OmZpcmVfY29yYWwECQBuYW1lX2hhc2hOHyyECVQVJwMKAG5ldHdvcmtfaWS9vF0UCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:brain_coral", - "block_state_b64": "CgAAAwgAYmxvY2tfaWREAwAACAQAbmFtZRUAbWluZWNyYWZ0OmJyYWluX2NvcmFsBAkAbmFtZV9oYXNoRiWlLCwA2ycDCgBuZXR3b3JrX2lkrjAuhgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWREAwAACAQAbmFtZRUAbWluZWNyYWZ0OmJyYWluX2NvcmFsBAkAbmFtZV9oYXNoRiWlLCwA2ycDCgBuZXR3b3JrX2lkrjAuhgoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:bubble_coral", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRFAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJ1YmJsZV9jb3JhbAQJAG5hbWVfaGFzaJz6rWnl+v2qAwoAbmV0d29ya19pZImIWy0KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRFAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJ1YmJsZV9jb3JhbAQJAG5hbWVfaGFzaJz6rWnl+v2qAwoAbmV0d29ya19pZImIWy0KBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:tube_coral", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAQAACAQAbmFtZRQAbWluZWNyYWZ0OnR1YmVfY29yYWwECQBuYW1lX2hhc2iYa8oO/tgk7wMKAG5ldHdvcmtfaWRTfND5CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAQAACAQAbmFtZRQAbWluZWNyYWZ0OnR1YmVfY29yYWwECQBuYW1lX2hhc2iYa8oO/tgk7wMKAG5ldHdvcmtfaWRTfND5CgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:horn_coral", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRHAwAACAQAbmFtZRQAbWluZWNyYWZ0Omhvcm5fY29yYWwECQBuYW1lX2hhc2iZnRHjZbnLPgMKAG5ldHdvcmtfaWR+GGp8CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRHAwAACAQAbmFtZRQAbWluZWNyYWZ0Omhvcm5fY29yYWwECQBuYW1lX2hhc2iZnRHjZbnLPgMKAG5ldHdvcmtfaWR+GGp8CgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:dead_fire_coral", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRLAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfZmlyZV9jb3JhbAQJAG5hbWVfaGFzaEPU6tFy/latAwoAbmV0d29ya19pZNMa7V4KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRLAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfZmlyZV9jb3JhbAQJAG5hbWVfaGFzaEPU6tFy/latAwoAbmV0d29ya19pZNMa7V4KBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:dead_brain_coral", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRJAwAACAQAbmFtZRoAbWluZWNyYWZ0OmRlYWRfYnJhaW5fY29yYWwECQBuYW1lX2hhc2j5L6QJCISvzwMKAG5ldHdvcmtfaWQkKzeiCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRJAwAACAQAbmFtZRoAbWluZWNyYWZ0OmRlYWRfYnJhaW5fY29yYWwECQBuYW1lX2hhc2j5L6QJCISvzwMKAG5ldHdvcmtfaWQkKzeiCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:dead_bubble_coral", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRKAwAACAQAbmFtZRsAbWluZWNyYWZ0OmRlYWRfYnViYmxlX2NvcmFsBAkAbmFtZV9oYXNoSTOZ/8wpeNYDCgBuZXR3b3JrX2lka6w9DAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRKAwAACAQAbmFtZRsAbWluZWNyYWZ0OmRlYWRfYnViYmxlX2NvcmFsBAkAbmFtZV9oYXNoSTOZ/8wpeNYDCgBuZXR3b3JrX2lka6w9DAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:dead_tube_coral", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRIAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfdHViZV9jb3JhbAQJAG5hbWVfaGFzaJGjNWhlaIJeAwoAbmV0d29ya19pZO3Z0ygKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRIAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfdHViZV9jb3JhbAQJAG5hbWVfaGFzaJGjNWhlaIJeAwoAbmV0d29ya19pZO3Z0ygKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:dead_horn_coral", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRMAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfaG9ybl9jb3JhbAQJAG5hbWVfaGFzaJBkz3qt+g2cAwoAbmV0d29ya19pZBAN+eYKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRMAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfaG9ybl9jb3JhbAQJAG5hbWVfaGFzaJBkz3qt+g2cAwoAbmV0d29ya19pZBAN+eYKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { - "id": "minecraft:coral_fan", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAQAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZOg7iS4KBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgMAcmVkAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "id": "minecraft:fire_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRJBAAACAQAbmFtZRgAbWluZWNyYWZ0OmZpcmVfY29yYWxfZmFuBAkAbmFtZV9oYXNosOTxYYxsDLgDCgBuZXR3b3JrX2lkFKxbEgoGAHN0YXRlcwMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { - "id": "minecraft:coral_fan", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAQAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZIDj8HMKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgQAcGluawMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "id": "minecraft:brain_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRHBAAACAQAbmFtZRkAbWluZWNyYWZ0OmJyYWluX2NvcmFsX2ZhbgQJAG5hbWVfaGFzaAi5uHizSNcqAwoAbmV0d29ya19pZFtLjNwKBgBzdGF0ZXMDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { - "id": "minecraft:coral_fan", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAQAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZLCJP0kKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgYAcHVycGxlAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "id": "minecraft:bubble_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRIBAAACAQAbmFtZRoAbWluZWNyYWZ0OmJ1YmJsZV9jb3JhbF9mYW4ECQBuYW1lX2hhc2hy/rX2on17DgMKAG5ldHdvcmtfaWQof60VCgYAc3RhdGVzAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { - "id": "minecraft:coral_fan", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAQAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZFz2ly4KBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgQAYmx1ZQMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "id": "minecraft:tube_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAQAACAQAbmFtZRgAbWluZWNyYWZ0OnR1YmVfY29yYWxfZmFuBAkAbmFtZV9oYXNo9pbJbo+PphIDCgBuZXR3b3JrX2lkenDTYgoGAHN0YXRlcwMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { - "id": "minecraft:coral_fan", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAQAACAQAbmFtZRMAbWluZWNyYWZ0OmNvcmFsX2ZhbgQJAG5hbWVfaGFzaAFROjbTm8JzAwoAbmV0d29ya19pZE4TgnYKBgBzdGF0ZXMICwBjb3JhbF9jb2xvcgYAeWVsbG93AxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "id": "minecraft:horn_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRKBAAACAQAbmFtZRgAbWluZWNyYWZ0Omhvcm5fY29yYWxfZmFuBAkAbmFtZV9oYXNoA+ri6NPDkbUDCgBuZXR3b3JrX2lkezoHNwoGAHN0YXRlcwMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { - "id": "minecraft:coral_fan_dead", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkdhLQzwoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "id": "minecraft:dead_fire_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRNBAAACAQAbmFtZR0AbWluZWNyYWZ0OmRlYWRfZmlyZV9jb3JhbF9mYW4ECQBuYW1lX2hhc2hpQO02NDxPvwMKAG5ldHdvcmtfaWTaOJgLCgYAc3RhdGVzAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { - "id": "minecraft:coral_fan_dead", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkSi6srQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "id": "minecraft:dead_brain_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRLBAAACAQAbmFtZR4AbWluZWNyYWZ0OmRlYWRfYnJhaW5fY29yYWxfZmFuBAkAbmFtZV9oYXNoI9/+Z4YqMhIDCgBuZXR3b3JrX2lkqYXxYgoGAHN0YXRlcwMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { - "id": "minecraft:coral_fan_dead", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkGiGSzAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "id": "minecraft:dead_bubble_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRMBAAACAQAbmFtZR8AbWluZWNyYWZ0OmRlYWRfYnViYmxlX2NvcmFsX2ZhbgQJAG5hbWVfaGFzaBNECtIM6VIOAwoAbmV0d29ya19pZLrNtBEKBgBzdGF0ZXMDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { - "id": "minecraft:coral_fan_dead", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lkmvZKOgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "id": "minecraft:dead_tube_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAQAACAQAbmFtZR0AbWluZWNyYWZ0OmRlYWRfdHViZV9jb3JhbF9mYW4ECQBuYW1lX2hhc2hbBBM9jFKWvQMKAG5ldHdvcmtfaWSkJKUWCgYAc3RhdGVzAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { - "id": "minecraft:coral_fan_dead", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNvcmFsX2Zhbl9kZWFkBAkAbmFtZV9oYXNo3kgokLV4uQIDCgBuZXR3b3JrX2lknLw+4QoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "id": "minecraft:dead_horn_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWROBAAACAQAbmFtZR0AbWluZWNyYWZ0OmRlYWRfaG9ybl9jb3JhbF9mYW4ECQBuYW1lX2hhc2hObElFrHfPygMKAG5ldHdvcmtfaWQ1ZxvmCgYAc3RhdGVzAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:crimson_roots", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTeAQAACAQAbmFtZRcAbWluZWNyYWZ0OmNyaW1zb25fcm9vdHMECQBuYW1lX2hhc2j1fWgQLViv5QMKAG5ldHdvcmtfaWRLh5DXCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTeAQAACAQAbmFtZRcAbWluZWNyYWZ0OmNyaW1zb25fcm9vdHMECQBuYW1lX2hhc2j1fWgQLViv5QMKAG5ldHdvcmtfaWRLh5DXCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:warped_roots", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAQAACAQAbmFtZRYAbWluZWNyYWZ0OndhcnBlZF9yb290cwQJAG5hbWVfaGFzaBc3WvbJOLlkAwoAbmV0d29ya19pZNLgDnAKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAQAACAQAbmFtZRYAbWluZWNyYWZ0OndhcnBlZF9yb290cwQJAG5hbWVfaGFzaBc3WvbJOLlkAwoAbmV0d29ya19pZNLgDnAKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:yellow_flower", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQlAAAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19mbG93ZXIECQBuYW1lX2hhc2jWbU1pF0OUGAMKAG5ldHdvcmtfaWQgO3hpCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQlAAAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19mbG93ZXIECQBuYW1lX2hhc2jWbU1pF0OUGAMKAG5ldHdvcmtfaWQgO3hpCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { - "id": "minecraft:red_flower", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWSqsqQGCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUFAHBvcHB5AAMHAHZlcnNpb24ERhQBAA==" + "id": "minecraft:poppy", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZQ8AbWluZWNyYWZ0OnBvcHB5BAkAbmFtZV9oYXNocMF8pITMbkcDCgBuZXR3b3JrX2lk8im6ywoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { - "id": "minecraft:red_flower", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWTqDajjCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUGAG9yY2hpZAADBwB2ZXJzaW9uBEYUAQA=" + "id": "minecraft:blue_orchid", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ9BAAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfb3JjaGlkBAkAbmFtZV9oYXNoBjz2MsgB21EDCgBuZXR3b3JrX2lk/iLsSwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { - "id": "minecraft:red_flower", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWT5CjveCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUGAGFsbGl1bQADBwB2ZXJzaW9uBEYUAQA=" + "id": "minecraft:allium", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ+BAAACAQAbmFtZRAAbWluZWNyYWZ0OmFsbGl1bQQJAG5hbWVfaGFzaDCGQBHNDTkcAwoAbmV0d29ya19pZD9Dgr0KBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { - "id": "minecraft:red_flower", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWTORIBJCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUJAGhvdXN0b25pYQADBwB2ZXJzaW9uBEYUAQA=" + "id": "minecraft:azure_bluet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ/BAAACAQAbmFtZRUAbWluZWNyYWZ0OmF6dXJlX2JsdWV0BAkAbmFtZV9oYXNo9N5egqMT2QcDCgBuZXR3b3JrX2lkwIgDnwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { - "id": "minecraft:red_flower", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWTuNhmYCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUJAHR1bGlwX3JlZAADBwB2ZXJzaW9uBEYUAQA=" + "id": "minecraft:red_tulip", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRABAAACAQAbmFtZRMAbWluZWNyYWZ0OnJlZF90dWxpcAQJAG5hbWVfaGFzaAjMi9Rd+6rhAwoAbmV0d29ya19pZAZCnt8KBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { - "id": "minecraft:red_flower", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWT0O4nfCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUMAHR1bGlwX29yYW5nZQADBwB2ZXJzaW9uBEYUAQA=" + "id": "minecraft:orange_tulip", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRBBAAACAQAbmFtZRYAbWluZWNyYWZ0Om9yYW5nZV90dWxpcAQJAG5hbWVfaGFzaP+NjxMBZ8vAAwoAbmV0d29ya19pZPYatsMKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { - "id": "minecraft:red_flower", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWTqkthyCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGULAHR1bGlwX3doaXRlAAMHAHZlcnNpb24ERhQBAA==" + "id": "minecraft:white_tulip", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRCBAAACAQAbmFtZRUAbWluZWNyYWZ0OndoaXRlX3R1bGlwBAkAbmFtZV9oYXNo5vbU4VRPh3ADCgBuZXR3b3JrX2lkok+4rQoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { - "id": "minecraft:red_flower", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRMbBA7CgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUKAHR1bGlwX3BpbmsAAwcAdmVyc2lvbgRGFAEA" + "id": "minecraft:pink_tulip", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRDBAAACAQAbmFtZRQAbWluZWNyYWZ0OnBpbmtfdHVsaXAECQBuYW1lX2hhc2hxDHZa6OaNXAMKAG5ldHdvcmtfaWTiOT+VCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { - "id": "minecraft:red_flower", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRexMAuCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUFAG94ZXllAAMHAHZlcnNpb24ERhQBAA==" + "id": "minecraft:oxeye_daisy", + "block_state_b64": "CgAAAwgAYmxvY2tfaWREBAAACAQAbmFtZRUAbWluZWNyYWZ0Om94ZXllX2RhaXN5BAkAbmFtZV9oYXNoXwxsqNQTN9gDCgBuZXR3b3JrX2lkw7R7dwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { - "id": "minecraft:red_flower", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWQgs7BECgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUKAGNvcm5mbG93ZXIAAwcAdmVyc2lvbgRGFAEA" + "id": "minecraft:cornflower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRFBAAACAQAbmFtZRQAbWluZWNyYWZ0OmNvcm5mbG93ZXIECQBuYW1lX2hhc2gnhyC3EeqHgAMKAG5ldHdvcmtfaWR4VrvACgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { - "id": "minecraft:red_flower", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9mbG93ZXIECQBuYW1lX2hhc2ixeWoRT8FNPwMKAG5ldHdvcmtfaWRvDuNbCgYAc3RhdGVzCAsAZmxvd2VyX3R5cGUSAGxpbHlfb2ZfdGhlX3ZhbGxleQADBwB2ZXJzaW9uBEYUAQA=" + "id": "minecraft:lily_of_the_valley", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRGBAAACAQAbmFtZRwAbWluZWNyYWZ0OmxpbHlfb2ZfdGhlX3ZhbGxleQQJAG5hbWVfaGFzaI64TJSf9mgQAwoAbmV0d29ya19pZFE9+nwKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { - "id": "minecraft:double_plant", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZOemRt4KBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQkAc3VuZmxvd2VyAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + "id": "minecraft:sunflower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRMAbWluZWNyYWZ0OnN1bmZsb3dlcgQJAG5hbWVfaGFzaAMxYQLoqlZ0AwoAbmV0d29ya19pZA10iSoKBgBzdGF0ZXMBDwB1cHBlcl9ibG9ja19iaXQAAAMHAHZlcnNpb24DABUBAA==" }, { - "id": "minecraft:double_plant", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZOFugoEKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQcAc3lyaW5nYQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "id": "minecraft:lilac", + "block_state_b64": "CgAAAwgAYmxvY2tfaWReBAAACAQAbmFtZQ8AbWluZWNyYWZ0OmxpbGFjBAkAbmFtZV9oYXNoD3nrQJuo7NkDCgBuZXR3b3JrX2lk5W+uFAoGAHN0YXRlcwEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { - "id": "minecraft:double_plant", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZN4O+/gKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQQAcm9zZQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "id": "minecraft:rose_bush", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhBAAACAQAbmFtZRMAbWluZWNyYWZ0OnJvc2VfYnVzaAQJAG5hbWVfaGFzaLoiFk8LVpGKAwoAbmV0d29ya19pZMZPv48KBgBzdGF0ZXMBDwB1cHBlcl9ibG9ja19iaXQAAAMHAHZlcnNpb24DABUBAA==" }, { - "id": "minecraft:double_plant", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRYAbWluZWNyYWZ0OmRvdWJsZV9wbGFudAQJAG5hbWVfaGFzaHVcUQvyXwGKAwoAbmV0d29ya19pZI3w4GMKBgBzdGF0ZXMIEQBkb3VibGVfcGxhbnRfdHlwZQcAcGFlb25pYQEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "id": "minecraft:peony", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiBAAACAQAbmFtZQ8AbWluZWNyYWZ0OnBlb255BAkAbmFtZV9oYXNoR4dYc4QquPADCgBuZXR3b3JrX2lkrTe7RwoGAHN0YXRlcwEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:pitcher_plant", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAwAACAQAbmFtZRcAbWluZWNyYWZ0OnBpdGNoZXJfcGxhbnQECQBuYW1lX2hhc2hRJHzsbDH+SQMKAG5ldHdvcmtfaWRnY76VCgYAc3RhdGVzAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAwAACAQAbmFtZRcAbWluZWNyYWZ0OnBpdGNoZXJfcGxhbnQECQBuYW1lX2hhc2hRJHzsbDH+SQMKAG5ldHdvcmtfaWRnY76VCgYAc3RhdGVzAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:pink_petals", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQkAwAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfcGV0YWxzBAkAbmFtZV9oYXNo6DQwN9SwV3QDCgBuZXR3b3JrX2lkNWneGgoGAHN0YXRlcwMGAGdyb3d0aAAAAAAIHABtaW5lY3JhZnQ6Y2FyZGluYWxfZGlyZWN0aW9uBQBzb3V0aAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQkAwAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfcGV0YWxzBAkAbmFtZV9oYXNo6DQwN9SwV3QDCgBuZXR3b3JrX2lkNWneGgoGAHN0YXRlcwMGAGdyb3d0aAAAAAAIHABtaW5lY3JhZnQ6Y2FyZGluYWxfZGlyZWN0aW9uBQBzb3V0aAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:wither_rose", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAQAACAQAbmFtZRUAbWluZWNyYWZ0OndpdGhlcl9yb3NlBAkAbmFtZV9oYXNoaSKxl3I516gDCgBuZXR3b3JrX2lkATXLPwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAQAACAQAbmFtZRUAbWluZWNyYWZ0OndpdGhlcl9yb3NlBAkAbmFtZV9oYXNoaSKxl3I516gDCgBuZXR3b3JrX2lkATXLPwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:torchflower", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ3AwAACAQAbmFtZRUAbWluZWNyYWZ0OnRvcmNoZmxvd2VyBAkAbmFtZV9oYXNoL+mHtElwbqQDCgBuZXR3b3JrX2lkI34O+AoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ3AwAACAQAbmFtZRUAbWluZWNyYWZ0OnRvcmNoZmxvd2VyBAkAbmFtZV9oYXNoL+mHtElwbqQDCgBuZXR3b3JrX2lkI34O+AoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:white_dye" @@ -2376,142 +2528,194 @@ }, { "id": "minecraft:vine", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRqAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnZpbmUECQBuYW1lX2hhc2j0Sj8/XeXOLAMKAG5ldHdvcmtfaWSUkDtbCgYAc3RhdGVzAxMAdmluZV9kaXJlY3Rpb25fYml0cwAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRqAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnZpbmUECQBuYW1lX2hhc2j0Sj8/XeXOLAMKAG5ldHdvcmtfaWSUkDtbCgYAc3RhdGVzAxMAdmluZV9kaXJlY3Rpb25fYml0cwAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:weeping_vines", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTmAQAACAQAbmFtZRcAbWluZWNyYWZ0OndlZXBpbmdfdmluZXMECQBuYW1lX2hhc2jrLgLHkQygiwMKAG5ldHdvcmtfaWQ8NHSJCgYAc3RhdGVzAxEAd2VlcGluZ192aW5lc19hZ2UAAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTmAQAACAQAbmFtZRcAbWluZWNyYWZ0OndlZXBpbmdfdmluZXMECQBuYW1lX2hhc2jrLgLHkQygiwMKAG5ldHdvcmtfaWQ8NHSJCgYAc3RhdGVzAxEAd2VlcGluZ192aW5lc19hZ2UAAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:twisting_vines", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQeAgAACAQAbmFtZRgAbWluZWNyYWZ0OnR3aXN0aW5nX3ZpbmVzBAkAbmFtZV9oYXNoDYR5QgVUQJADCgBuZXR3b3JrX2lk5kYVIQoGAHN0YXRlcwMSAHR3aXN0aW5nX3ZpbmVzX2FnZQAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQeAgAACAQAbmFtZRgAbWluZWNyYWZ0OnR3aXN0aW5nX3ZpbmVzBAkAbmFtZV9oYXNoDYR5QgVUQJADCgBuZXR3b3JrX2lk5kYVIQoGAHN0YXRlcwMSAHR3aXN0aW5nX3ZpbmVzX2FnZQAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:waterlily", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRvAAAACAQAbmFtZRMAbWluZWNyYWZ0OndhdGVybGlseQQJAG5hbWVfaGFzaEHgC4c1SXg0AwoAbmV0d29ya19pZOOerp8KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRvAAAACAQAbmFtZRMAbWluZWNyYWZ0OndhdGVybGlseQQJAG5hbWVfaGFzaEHgC4c1SXg0AwoAbmV0d29ya19pZOOerp8KBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:seagrass", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAQAACAQAbmFtZRIAbWluZWNyYWZ0OnNlYWdyYXNzBAkAbmFtZV9oYXNoHSBFtoHdWxIDCgBuZXR3b3JrX2lkd3lhEAoGAHN0YXRlcwgOAHNlYV9ncmFzc190eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAQAACAQAbmFtZRIAbWluZWNyYWZ0OnNlYWdyYXNzBAkAbmFtZV9oYXNoHSBFtoHdWxIDCgBuZXR3b3JrX2lkd3lhEAoGAHN0YXRlcwgOAHNlYV9ncmFzc190eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:kelp" }, { "id": "minecraft:deadbush", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQgAAAACAQAbmFtZRIAbWluZWNyYWZ0OmRlYWRidXNoBAkAbmFtZV9oYXNoPFODe4IScnYDCgBuZXR3b3JrX2lkVfnl+goGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQgAAAACAQAbmFtZRIAbWluZWNyYWZ0OmRlYWRidXNoBAkAbmFtZV9oYXNoPFODe4IScnYDCgBuZXR3b3JrX2lkVfnl+goGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:bamboo", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAQAACAQAbmFtZRAAbWluZWNyYWZ0OmJhbWJvbwQJAG5hbWVfaGFzaBgpGmyzhedCAwoAbmV0d29ya19pZIZv1nYKBgBzdGF0ZXMBBwBhZ2VfYml0AAgQAGJhbWJvb19sZWFmX3NpemUJAG5vX2xlYXZlcwgWAGJhbWJvb19zdGFsa190aGlja25lc3MEAHRoaW4AAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAQAACAQAbmFtZRAAbWluZWNyYWZ0OmJhbWJvbwQJAG5hbWVfaGFzaBgpGmyzhedCAwoAbmV0d29ya19pZIZv1nYKBgBzdGF0ZXMBBwBhZ2VfYml0AAgQAGJhbWJvb19sZWFmX3NpemUJAG5vX2xlYXZlcwgWAGJhbWJvb19zdGFsa190aGlja25lc3MEAHRoaW4AAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:snow", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRQAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnNub3cECQBuYW1lX2hhc2gVHr5XXdETWAMKAG5ldHdvcmtfaWQ0zCeHCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRQAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnNub3cECQBuYW1lX2hhc2gVHr5XXdETWAMKAG5ldHdvcmtfaWQ0zCeHCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:ice", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRPAAAACAQAbmFtZQ0AbWluZWNyYWZ0OmljZQQJAG5hbWVfaGFzaNF26f+uUT29AwoAbmV0d29ya19pZOUMaQYKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRPAAAACAQAbmFtZQ0AbWluZWNyYWZ0OmljZQQJAG5hbWVfaGFzaNF26f+uUT29AwoAbmV0d29ya19pZOUMaQYKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:packed_ice", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSuAAAACAQAbmFtZRQAbWluZWNyYWZ0OnBhY2tlZF9pY2UECQBuYW1lX2hhc2hk4bu123ZrFgMKAG5ldHdvcmtfaWTr/ooaCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSuAAAACAQAbmFtZRQAbWluZWNyYWZ0OnBhY2tlZF9pY2UECQBuYW1lX2hhc2hk4bu123ZrFgMKAG5ldHdvcmtfaWTr/ooaCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:blue_ice", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQKAQAACAQAbmFtZRIAbWluZWNyYWZ0OmJsdWVfaWNlBAkAbmFtZV9oYXNo+EKxYgFhKcgDCgBuZXR3b3JrX2lkxfsA8goGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQKAQAACAQAbmFtZRIAbWluZWNyYWZ0OmJsdWVfaWNlBAkAbmFtZV9oYXNo+EKxYgFhKcgDCgBuZXR3b3JrX2lkxfsA8goGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:snow_layer", - "block_state_b64": "CgAAAwgAYmxvY2tfaWROAAAACAQAbmFtZRQAbWluZWNyYWZ0OnNub3dfbGF5ZXIECQBuYW1lX2hhc2hXka6atMYUCQMKAG5ldHdvcmtfaWRCrIPcCgYAc3RhdGVzAQsAY292ZXJlZF9iaXQAAwYAaGVpZ2h0AAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWROAAAACAQAbmFtZRQAbWluZWNyYWZ0OnNub3dfbGF5ZXIECQBuYW1lX2hhc2hXka6atMYUCQMKAG5ldHdvcmtfaWRCrIPcCgYAc3RhdGVzAQsAY292ZXJlZF9iaXQAAwYAaGVpZ2h0AAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:pointed_dripstone", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQzAgAACAQAbmFtZRsAbWluZWNyYWZ0OnBvaW50ZWRfZHJpcHN0b25lBAkAbmFtZV9oYXNoJMISzmHQgt8DCgBuZXR3b3JrX2lkbWrtYgoGAHN0YXRlcwgTAGRyaXBzdG9uZV90aGlja25lc3MDAHRpcAEHAGhhbmdpbmcBAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQzAgAACAQAbmFtZRsAbWluZWNyYWZ0OnBvaW50ZWRfZHJpcHN0b25lBAkAbmFtZV9oYXNoJMISzmHQgt8DCgBuZXR3b3JrX2lkbWrtYgoGAHN0YXRlcwgTAGRyaXBzdG9uZV90aGlja25lc3MDAHRpcAEHAGhhbmdpbmcBAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:dripstone_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ8AgAACAQAbmFtZRkAbWluZWNyYWZ0OmRyaXBzdG9uZV9ibG9jawQJAG5hbWVfaGFzaIIXnEqY77YsAwoAbmV0d29ya19pZMZi2kwKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ8AgAACAQAbmFtZRkAbWluZWNyYWZ0OmRyaXBzdG9uZV9ibG9jawQJAG5hbWVfaGFzaIIXnEqY77YsAwoAbmV0d29ya19pZMZi2kwKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:moss_carpet", - "block_state_b64": "CgAAAwgAYmxvY2tfaWROAgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vc3NfY2FycGV0BAkAbmFtZV9oYXNo/NEDxRPTshYDCgBuZXR3b3JrX2lkaGG3QwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWROAgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vc3NfY2FycGV0BAkAbmFtZV9oYXNo/NEDxRPTshYDCgBuZXR3b3JrX2lkaGG3QwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:moss_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ/AgAACAQAbmFtZRQAbWluZWNyYWZ0Om1vc3NfYmxvY2sECQBuYW1lX2hhc2iovcsPUYX2tgMKAG5ldHdvcmtfaWT3JSbfCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ/AgAACAQAbmFtZRQAbWluZWNyYWZ0Om1vc3NfYmxvY2sECQBuYW1lX2hhc2iovcsPUYX2tgMKAG5ldHdvcmtfaWT3JSbfCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:dirt_with_roots", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ9AgAACAQAbmFtZRkAbWluZWNyYWZ0OmRpcnRfd2l0aF9yb290cwQJAG5hbWVfaGFzaLCNDYPviDCIAwoAbmV0d29ya19pZNCkwzoKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ9AgAACAQAbmFtZRkAbWluZWNyYWZ0OmRpcnRfd2l0aF9yb290cwQJAG5hbWVfaGFzaLCNDYPviDCIAwoAbmV0d29ya19pZNCkwzoKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:hanging_roots", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ+AgAACAQAbmFtZRcAbWluZWNyYWZ0Omhhbmdpbmdfcm9vdHMECQBuYW1lX2hhc2jaXn+Y5UZpDAMKAG5ldHdvcmtfaWRU4c2vCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ+AgAACAQAbmFtZRcAbWluZWNyYWZ0Omhhbmdpbmdfcm9vdHMECQBuYW1lX2hhc2jaXn+Y5UZpDAMKAG5ldHdvcmtfaWRU4c2vCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:mangrove_roots", - "block_state_b64": "CgAAAwgAYmxvY2tfaWThAgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hbmdyb3ZlX3Jvb3RzBAkAbmFtZV9oYXNoa786PzQGZ6kDCgBuZXR3b3JrX2lklA0AHgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWThAgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hbmdyb3ZlX3Jvb3RzBAkAbmFtZV9oYXNoa786PzQGZ6kDCgBuZXR3b3JrX2lklA0AHgoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:muddy_mangrove_roots", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAgAACAQAbmFtZR4AbWluZWNyYWZ0Om11ZGR5X21hbmdyb3ZlX3Jvb3RzBAkAbmFtZV9oYXNo9YApdHpo1RkDCgBuZXR3b3JrX2lkH0Oc4woGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAgAACAQAbmFtZR4AbWluZWNyYWZ0Om11ZGR5X21hbmdyb3ZlX3Jvb3RzBAkAbmFtZV9oYXNo9YApdHpo1RkDCgBuZXR3b3JrX2lkH0Oc4woGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:big_dripleaf", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRCAgAACAQAbmFtZRYAbWluZWNyYWZ0OmJpZ19kcmlwbGVhZgQJAG5hbWVfaGFzaGBEhXjo6qSdAwoAbmV0d29ya19pZMETsb8KBgBzdGF0ZXMBEQBiaWdfZHJpcGxlYWZfaGVhZAEIEQBiaWdfZHJpcGxlYWZfdGlsdAQAbm9uZQgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRCAgAACAQAbmFtZRYAbWluZWNyYWZ0OmJpZ19kcmlwbGVhZgQJAG5hbWVfaGFzaGBEhXjo6qSdAwoAbmV0d29ya19pZMETsb8KBgBzdGF0ZXMBEQBiaWdfZHJpcGxlYWZfaGVhZAEIEQBiaWdfZHJpcGxlYWZfdGlsdAQAbm9uZQgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:small_dripleaf_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRPAgAACAQAbmFtZR4AbWluZWNyYWZ0OnNtYWxsX2RyaXBsZWFmX2Jsb2NrBAkAbmFtZV9oYXNojxRAgXP9uWADCgBuZXR3b3JrX2lkozbVPwoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24EAGVhc3QBDwB1cHBlcl9ibG9ja19iaXQBAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRPAgAACAQAbmFtZR4AbWluZWNyYWZ0OnNtYWxsX2RyaXBsZWFmX2Jsb2NrBAkAbmFtZV9oYXNojxRAgXP9uWADCgBuZXR3b3JrX2lkozbVPwoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24EAGVhc3QBDwB1cHBlcl9ibG9ja19iaXQBAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:spore_blossom", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRAAgAACAQAbmFtZRcAbWluZWNyYWZ0OnNwb3JlX2Jsb3Nzb20ECQBuYW1lX2hhc2il3U72Gbco2gMKAG5ldHdvcmtfaWSbbbgcCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRAAgAACAQAbmFtZRcAbWluZWNyYWZ0OnNwb3JlX2Jsb3Nzb20ECQBuYW1lX2hhc2il3U72Gbco2gMKAG5ldHdvcmtfaWSbbbgcCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:azalea", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRQAgAACAQAbmFtZRAAbWluZWNyYWZ0OmF6YWxlYQQJAG5hbWVfaGFzaNyUl+BW9JrBAwoAbmV0d29ya19pZO/XZtQKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRQAgAACAQAbmFtZRAAbWluZWNyYWZ0OmF6YWxlYQQJAG5hbWVfaGFzaNyUl+BW9JrBAwoAbmV0d29ya19pZO/XZtQKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:flowering_azalea", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRRAgAACAQAbmFtZRoAbWluZWNyYWZ0OmZsb3dlcmluZ19hemFsZWEECQBuYW1lX2hhc2ie9r33wz8kiwMKAG5ldHdvcmtfaWQ3ij0VCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRRAgAACAQAbmFtZRoAbWluZWNyYWZ0OmZsb3dlcmluZ19hemFsZWEECQBuYW1lX2hhc2ie9r33wz8kiwMKAG5ldHdvcmtfaWQ3ij0VCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:glow_lichen", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSaAgAACAQAbmFtZRUAbWluZWNyYWZ0Omdsb3dfbGljaGVuBAkAbmFtZV9oYXNobyPUrIYlo44DCgBuZXR3b3JrX2lkCh8lSAoGAHN0YXRlcwMZAG11bHRpX2ZhY2VfZGlyZWN0aW9uX2JpdHM/AAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSaAgAACAQAbmFtZRUAbWluZWNyYWZ0Omdsb3dfbGljaGVuBAkAbmFtZV9oYXNobyPUrIYlo44DCgBuZXR3b3JrX2lkCh8lSAoGAHN0YXRlcwMZAG11bHRpX2ZhY2VfZGlyZWN0aW9uX2JpdHM/AAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:amethyst_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRGAgAACAQAbmFtZRgAbWluZWNyYWZ0OmFtZXRoeXN0X2Jsb2NrBAkAbmFtZV9oYXNob+JK1iiAthcDCgBuZXR3b3JrX2lk8HtpzgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRGAgAACAQAbmFtZRgAbWluZWNyYWZ0OmFtZXRoeXN0X2Jsb2NrBAkAbmFtZV9oYXNob+JK1iiAthcDCgBuZXR3b3JrX2lk8HtpzgoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:budding_amethyst", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRHAgAACAQAbmFtZRoAbWluZWNyYWZ0OmJ1ZGRpbmdfYW1ldGh5c3QECQBuYW1lX2hhc2gJvAwfI14fxgMKAG5ldHdvcmtfaWTQYqfACgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRHAgAACAQAbmFtZRoAbWluZWNyYWZ0OmJ1ZGRpbmdfYW1ldGh5c3QECQBuYW1lX2hhc2gJvAwfI14fxgMKAG5ldHdvcmtfaWTQYqfACgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:amethyst_cluster", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRIAgAACAQAbmFtZRoAbWluZWNyYWZ0OmFtZXRoeXN0X2NsdXN0ZXIECQBuYW1lX2hhc2jK82S88Jgm8wMKAG5ldHdvcmtfaWSCPMPGCgYAc3RhdGVzCBQAbWluZWNyYWZ0OmJsb2NrX2ZhY2UCAHVwAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRIAgAACAQAbmFtZRoAbWluZWNyYWZ0OmFtZXRoeXN0X2NsdXN0ZXIECQBuYW1lX2hhc2jK82S88Jgm8wMKAG5ldHdvcmtfaWSCPMPGCgYAc3RhdGVzCBQAbWluZWNyYWZ0OmJsb2NrX2ZhY2UCAHVwAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:large_amethyst_bud", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRJAgAACAQAbmFtZRwAbWluZWNyYWZ0OmxhcmdlX2FtZXRoeXN0X2J1ZAQJAG5hbWVfaGFzaAHhdpWD+sd5AwoAbmV0d29ya19pZKkQxOcKBgBzdGF0ZXMIFABtaW5lY3JhZnQ6YmxvY2tfZmFjZQIAdXAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRJAgAACAQAbmFtZRwAbWluZWNyYWZ0OmxhcmdlX2FtZXRoeXN0X2J1ZAQJAG5hbWVfaGFzaAHhdpWD+sd5AwoAbmV0d29ya19pZKkQxOcKBgBzdGF0ZXMIFABtaW5lY3JhZnQ6YmxvY2tfZmFjZQIAdXAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:medium_amethyst_bud", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRKAgAACAQAbmFtZR0AbWluZWNyYWZ0Om1lZGl1bV9hbWV0aHlzdF9idWQECQBuYW1lX2hhc2g5lBGtC0DzZQMKAG5ldHdvcmtfaWSYiP4gCgYAc3RhdGVzCBQAbWluZWNyYWZ0OmJsb2NrX2ZhY2UCAHVwAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRKAgAACAQAbmFtZR0AbWluZWNyYWZ0Om1lZGl1bV9hbWV0aHlzdF9idWQECQBuYW1lX2hhc2g5lBGtC0DzZQMKAG5ldHdvcmtfaWSYiP4gCgYAc3RhdGVzCBQAbWluZWNyYWZ0OmJsb2NrX2ZhY2UCAHVwAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:small_amethyst_bud", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRLAgAACAQAbmFtZRwAbWluZWNyYWZ0OnNtYWxsX2FtZXRoeXN0X2J1ZAQJAG5hbWVfaGFzaEnb4+q9PO4YAwoAbmV0d29ya19pZGWzxrQKBgBzdGF0ZXMIFABtaW5lY3JhZnQ6YmxvY2tfZmFjZQIAdXAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRLAgAACAQAbmFtZRwAbWluZWNyYWZ0OnNtYWxsX2FtZXRoeXN0X2J1ZAQJAG5hbWVfaGFzaEnb4+q9PO4YAwoAbmV0d29ya19pZGWzxrQKBgBzdGF0ZXMIFABtaW5lY3JhZnQ6YmxvY2tfZmFjZQIAdXAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:tuff", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRMAgAACAQAbmFtZQ4AbWluZWNyYWZ0OnR1ZmYECQBuYW1lX2hhc2h1Rwc1XYsBGwMKAG5ldHdvcmtfaWRwQGn0CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRMAgAACAQAbmFtZQ4AbWluZWNyYWZ0OnR1ZmYECQBuYW1lX2hhc2h1Rwc1XYsBGwMKAG5ldHdvcmtfaWRwQGn0CgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" + }, + { + "id": "minecraft:tuff_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTpAwAACAQAbmFtZRUAbWluZWNyYWZ0OnR1ZmZfc3RhaXJzBAkAbmFtZV9oYXNoKjyNUBjcfZsDCgBuZXR3b3JrX2lk+LsycgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" + }, + { + "id": "minecraft:tuff_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTnAwAACAQAbmFtZRMAbWluZWNyYWZ0OnR1ZmZfc2xhYgQJAG5hbWVfaGFzaIhCGdlIsnMUAwoAbmV0d29ya19pZN1dUL4KBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DABUBAA==" + }, + { + "id": "minecraft:tuff_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTqAwAACAQAbmFtZRMAbWluZWNyYWZ0OnR1ZmZfd2FsbAQJAG5hbWVfaGFzaMyeeu1IRf03AwoAbmV0d29ya19pZDkIrosKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uAwAVAQA=" + }, + { + "id": "minecraft:chiseled_tuff", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTwAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoaXNlbGVkX3R1ZmYECQBuYW1lX2hhc2iVliOT8OTQ9AMKAG5ldHdvcmtfaWTLNKOiCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" + }, + { + "id": "minecraft:polished_tuff", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTrAwAACAQAbmFtZRcAbWluZWNyYWZ0OnBvbGlzaGVkX3R1ZmYECQBuYW1lX2hhc2hyaLe/KEVZ0gMKAG5ldHdvcmtfaWTcX3NrCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" + }, + { + "id": "minecraft:polished_tuff_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTuAwAACAQAbmFtZR4AbWluZWNyYWZ0OnBvbGlzaGVkX3R1ZmZfc3RhaXJzBAkAbmFtZV9oYXNo8yuah8QI1dcDCgBuZXR3b3JrX2lkjLoU4AoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" + }, + { + "id": "minecraft:polished_tuff_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTsAwAACAQAbmFtZRwAbWluZWNyYWZ0OnBvbGlzaGVkX3R1ZmZfc2xhYgQJAG5hbWVfaGFzaLXdb48YvAsHAwoAbmV0d29ya19pZAnJ7W0KBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DABUBAA==" + }, + { + "id": "minecraft:polished_tuff_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTvAwAACAQAbmFtZRwAbWluZWNyYWZ0OnBvbGlzaGVkX3R1ZmZfd2FsbAQJAG5hbWVfaGFzaJVZj6QYWXUrAwoAbmV0d29ya19pZLU7dooKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uAwAVAQA=" + }, + { + "id": "minecraft:tuff_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTxAwAACAQAbmFtZRUAbWluZWNyYWZ0OnR1ZmZfYnJpY2tzBAkAbmFtZV9oYXNo/hbQ+mXSK7wDCgBuZXR3b3JrX2lk6gmIwQoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" + }, + { + "id": "minecraft:tuff_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT0AwAACAQAbmFtZRsAbWluZWNyYWZ0OnR1ZmZfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNoWJpkAurUfKwDCgBuZXR3b3JrX2lkUMcjiwoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" + }, + { + "id": "minecraft:tuff_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTyAwAACAQAbmFtZRkAbWluZWNyYWZ0OnR1ZmZfYnJpY2tfc2xhYgQJAG5hbWVfaGFzaLqPMjVCv5dIAwoAbmV0d29ya19pZOmeRhcKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24DABUBAA==" + }, + { + "id": "minecraft:tuff_brick_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT1AwAACAQAbmFtZRkAbWluZWNyYWZ0OnR1ZmZfYnJpY2tfd2FsbAQJAG5hbWVfaGFzaIL0IyNCOsonAwoAbmV0d29ya19pZJW4T5UKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uAwAVAQA=" + }, + { + "id": "minecraft:chiseled_tuff_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT2AwAACAQAbmFtZR4AbWluZWNyYWZ0OmNoaXNlbGVkX3R1ZmZfYnJpY2tzBAkAbmFtZV9oYXNo3oQw6gmxYuADCgBuZXR3b3JrX2lkm3D8AgoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:calcite", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRFAgAACAQAbmFtZREAbWluZWNyYWZ0OmNhbGNpdGUECQBuYW1lX2hhc2ixKLu8ZIdzDQMKAG5ldHdvcmtfaWQlSbJDCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRFAgAACAQAbmFtZREAbWluZWNyYWZ0OmNhbGNpdGUECQBuYW1lX2hhc2ixKLu8ZIdzDQMKAG5ldHdvcmtfaWQlSbJDCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:chicken" @@ -2542,35 +2746,35 @@ }, { "id": "minecraft:brown_mushroom", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQnAAAACAQAbmFtZRgAbWluZWNyYWZ0OmJyb3duX211c2hyb29tBAkAbmFtZV9oYXNonYw/FO78WDoDCgBuZXR3b3JrX2lkLh1OXAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQnAAAACAQAbmFtZRgAbWluZWNyYWZ0OmJyb3duX211c2hyb29tBAkAbmFtZV9oYXNonYw/FO78WDoDCgBuZXR3b3JrX2lkLh1OXAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:red_mushroom", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQoAAAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZF9tdXNocm9vbQQJAG5hbWVfaGFzaPpzJua7669xAwoAbmV0d29ya19pZCvWPYkKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQoAAAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZF9tdXNocm9vbQQJAG5hbWVfaGFzaPpzJua7669xAwoAbmV0d29ya19pZCvWPYkKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:crimson_fungus", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fZnVuZ3VzBAkAbmFtZV9oYXNolIcCUuFM2u0DCgBuZXR3b3JrX2lkD2NN0QoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fZnVuZ3VzBAkAbmFtZV9oYXNolIcCUuFM2u0DCgBuZXR3b3JrX2lkD2NN0QoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:warped_fungus", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9mdW5ndXMECQBuYW1lX2hhc2gq8bSnRVTAFgMKAG5ldHdvcmtfaWTkwS+rCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9mdW5ndXMECQBuYW1lX2hhc2gq8bSnRVTAFgMKAG5ldHdvcmtfaWTkwS+rCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:brown_mushroom_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAAAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkdOMhDAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cw4AAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAAAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkdOMhDAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cw4AAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:red_mushroom_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRkAAAACAQAbmFtZRwAbWluZWNyYWZ0OnJlZF9tdXNocm9vbV9ibG9jawQJAG5hbWVfaGFzaJTTyJbth9M9AwoAbmV0d29ya19pZM+AyboKBgBzdGF0ZXMDEgBodWdlX211c2hyb29tX2JpdHMOAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRkAAAACAQAbmFtZRwAbWluZWNyYWZ0OnJlZF9tdXNocm9vbV9ibG9jawQJAG5hbWVfaGFzaJTTyJbth9M9AwoAbmV0d29ya19pZM+AyboKBgBzdGF0ZXMDEgBodWdlX211c2hyb29tX2JpdHMOAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:brown_mushroom_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAAAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkbdt3CAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cw8AAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAAAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkbdt3CAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cw8AAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:brown_mushroom_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAAAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkSrMl9goGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cwAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAAAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkSrMl9goGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cwAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:egg" @@ -2589,74 +2793,82 @@ }, { "id": "minecraft:web", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQeAAAACAQAbmFtZQ0AbWluZWNyYWZ0OndlYgQJAG5hbWVfaGFzaA4GKQCvG4i9AwoAbmV0d29ya19pZApt+jgKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQeAAAACAQAbmFtZQ0AbWluZWNyYWZ0OndlYgQJAG5hbWVfaGFzaA4GKQCvG4i9AwoAbmV0d29ya19pZApt+jgKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:spider_eye" }, { "id": "minecraft:mob_spawner", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ0AAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vYl9zcGF3bmVyBAkAbmFtZV9oYXNoNwGrCV/Fkh8DCgBuZXR3b3JrX2lkM1wTmgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ0AAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vYl9zcGF3bmVyBAkAbmFtZV9oYXNoNwGrCV/Fkh8DCgBuZXR3b3JrX2lkM1wTmgoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" + }, + { + "id": "minecraft:trial_spawner", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ6AgAACAQAbmFtZRcAbWluZWNyYWZ0OnRyaWFsX3NwYXduZXIECQBuYW1lX2hhc2iNLRPB4ACz+QMKAG5ldHdvcmtfaWTWFYHGCgYAc3RhdGVzAQcAb21pbm91cwADEwB0cmlhbF9zcGF3bmVyX3N0YXRlAAAAAAADBwB2ZXJzaW9uAwAVAQA=" + }, + { + "id": "minecraft:vault", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ5AgAACAQAbmFtZQ8AbWluZWNyYWZ0OnZhdWx0BAkAbmFtZV9oYXNoCAp9n3IAyqcDCgBuZXR3b3JrX2lk6/P+vwoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAQcAb21pbm91cwAICwB2YXVsdF9zdGF0ZQgAaW5hY3RpdmUAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:end_portal_frame", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR4AAAACAQAbmFtZRoAbWluZWNyYWZ0OmVuZF9wb3J0YWxfZnJhbWUECQBuYW1lX2hhc2gqofyUIjGOpQMKAG5ldHdvcmtfaWRbGHf8CgYAc3RhdGVzARIAZW5kX3BvcnRhbF9leWVfYml0AAgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR4AAAACAQAbmFtZRoAbWluZWNyYWZ0OmVuZF9wb3J0YWxfZnJhbWUECQBuYW1lX2hhc2gqofyUIjGOpQMKAG5ldHdvcmtfaWRbGHf8CgYAc3RhdGVzARIAZW5kX3BvcnRhbF9leWVfYml0AAgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:monster_egg", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkqXH7RgoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUFAHN0b25lAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkqXH7RgoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUFAHN0b25lAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:monster_egg", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkeIBb6QoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGULAGNvYmJsZXN0b25lAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkeIBb6QoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGULAGNvYmJsZXN0b25lAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:monster_egg", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkDZ2cFQoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGULAHN0b25lX2JyaWNrAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkDZ2cFQoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGULAHN0b25lX2JyaWNrAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:monster_egg", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkOR/cTAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGURAG1vc3N5X3N0b25lX2JyaWNrAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkOR/cTAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGURAG1vc3N5X3N0b25lX2JyaWNrAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:monster_egg", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkqdwlHAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUTAGNyYWNrZWRfc3RvbmVfYnJpY2sAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkqdwlHAoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUTAGNyYWNrZWRfc3RvbmVfYnJpY2sAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:monster_egg", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkFqqPggoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUUAGNoaXNlbGVkX3N0b25lX2JyaWNrAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vbnN0ZXJfZWdnBAkAbmFtZV9oYXNoFMxMALksxVEDCgBuZXR3b3JrX2lkFqqPggoGAHN0YXRlcwgWAG1vbnN0ZXJfZWdnX3N0b25lX3R5cGUUAGNoaXNlbGVkX3N0b25lX2JyaWNrAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:infested_deepslate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTFAgAACAQAbmFtZRwAbWluZWNyYWZ0OmluZmVzdGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaICF2VYccxF1AwoAbmV0d29ya19pZDa/624KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTFAgAACAQAbmFtZRwAbWluZWNyYWZ0OmluZmVzdGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaICF2VYccxF1AwoAbmV0d29ya19pZDa/624KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:dragon_egg", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR6AAAACAQAbmFtZRQAbWluZWNyYWZ0OmRyYWdvbl9lZ2cECQBuYW1lX2hhc2inMzXrV+/e1wMKAG5ldHdvcmtfaWTgO1yRCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR6AAAACAQAbmFtZRQAbWluZWNyYWZ0OmRyYWdvbl9lZ2cECQBuYW1lX2hhc2inMzXrV+/e1wMKAG5ldHdvcmtfaWTgO1yRCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:turtle_egg", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAQAACAQAbmFtZRQAbWluZWNyYWZ0OnR1cnRsZV9lZ2cECQBuYW1lX2hhc2iwSRcxOJIJ9gMKAG5ldHdvcmtfaWSIRNUhCgYAc3RhdGVzCA0AY3JhY2tlZF9zdGF0ZQkAbm9fY3JhY2tzCBAAdHVydGxlX2VnZ19jb3VudAcAb25lX2VnZwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAQAACAQAbmFtZRQAbWluZWNyYWZ0OnR1cnRsZV9lZ2cECQBuYW1lX2hhc2iwSRcxOJIJ9gMKAG5ldHdvcmtfaWSIRNUhCgYAc3RhdGVzCA0AY3JhY2tlZF9zdGF0ZQkAbm9fY3JhY2tzCBAAdHVydGxlX2VnZ19jb3VudAcAb25lX2VnZwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:sniffer_egg", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRTAwAACAQAbmFtZRUAbWluZWNyYWZ0OnNuaWZmZXJfZWdnBAkAbmFtZV9oYXNoY1lozc8lPcYDCgBuZXR3b3JrX2lk7yb/2QoGAHN0YXRlcwgNAGNyYWNrZWRfc3RhdGUJAG5vX2NyYWNrcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRTAwAACAQAbmFtZRUAbWluZWNyYWZ0OnNuaWZmZXJfZWdnBAkAbmFtZV9oYXNoY1lozc8lPcYDCgBuZXR3b3JrX2lk7yb/2QoGAHN0YXRlcwgNAGNyYWNrZWRfc3RhdGUJAG5vX2NyYWNrcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:frog_spawn", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAgAACAQAbmFtZRQAbWluZWNyYWZ0OmZyb2dfc3Bhd24ECQBuYW1lX2hhc2iWmd7idp3ZZwMKAG5ldHdvcmtfaWRFzJudCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAgAACAQAbmFtZRQAbWluZWNyYWZ0OmZyb2dfc3Bhd24ECQBuYW1lX2hhc2iWmd7idp3ZZwMKAG5ldHdvcmtfaWRFzJudCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:pearlescent_froglight", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTUAgAACAQAbmFtZR8AbWluZWNyYWZ0OnBlYXJsZXNjZW50X2Zyb2dsaWdodAQJAG5hbWVfaGFzaKkcFRyycYGyAwoAbmV0d29ya19pZJqYakAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTUAgAACAQAbmFtZR8AbWluZWNyYWZ0OnBlYXJsZXNjZW50X2Zyb2dsaWdodAQJAG5hbWVfaGFzaKkcFRyycYGyAwoAbmV0d29ya19pZJqYakAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:verdant_froglight", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTVAgAACAQAbmFtZRsAbWluZWNyYWZ0OnZlcmRhbnRfZnJvZ2xpZ2h0BAkAbmFtZV9oYXNoA+eXuTBohrQDCgBuZXR3b3JrX2lkDIVnsQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTVAgAACAQAbmFtZRsAbWluZWNyYWZ0OnZlcmRhbnRfZnJvZ2xpZ2h0BAkAbmFtZV9oYXNoA+eXuTBohrQDCgBuZXR3b3JrX2lkDIVnsQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:ochre_froglight", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTWAgAACAQAbmFtZRkAbWluZWNyYWZ0Om9jaHJlX2Zyb2dsaWdodAQJAG5hbWVfaGFzaMY59kjPe+c3AwoAbmV0d29ya19pZO2TD50KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTWAgAACAQAbmFtZRkAbWluZWNyYWZ0Om9jaHJlX2Zyb2dsaWdodAQJAG5hbWVfaGFzaMY59kjPe+c3AwoAbmV0d29ya19pZO2TD50KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:chicken_spawn_egg" @@ -2883,40 +3095,49 @@ { "id": "minecraft:sniffer_spawn_egg" }, + { + "id": "minecraft:breeze_spawn_egg" + }, + { + "id": "minecraft:armadillo_spawn_egg" + }, + { + "id": "minecraft:bogged_spawn_egg" + }, { "id": "minecraft:obsidian", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQxAAAACAQAbmFtZRIAbWluZWNyYWZ0Om9ic2lkaWFuBAkAbmFtZV9oYXNoiz4qrb8QjyEDCgBuZXR3b3JrX2lkuqnPpQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQxAAAACAQAbmFtZRIAbWluZWNyYWZ0Om9ic2lkaWFuBAkAbmFtZV9oYXNoiz4qrb8QjyEDCgBuZXR3b3JrX2lkuqnPpQoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:crying_obsidian", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQgAgAACAQAbmFtZRkAbWluZWNyYWZ0OmNyeWluZ19vYnNpZGlhbgQJAG5hbWVfaGFzaKT0JlA7Z1K+AwoAbmV0d29ya19pZCjbPV4KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQgAgAACAQAbmFtZRkAbWluZWNyYWZ0OmNyeWluZ19vYnNpZGlhbgQJAG5hbWVfaGFzaKT0JlA7Z1K+AwoAbmV0d29ya19pZCjbPV4KBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:bedrock", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAAAACAQAbmFtZREAbWluZWNyYWZ0OmJlZHJvY2sECQBuYW1lX2hhc2hWfFrh4LVtxwMKAG5ldHdvcmtfaWT7fKz1CgYAc3RhdGVzAQ4AaW5maW5pYnVybl9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAAAACAQAbmFtZREAbWluZWNyYWZ0OmJlZHJvY2sECQBuYW1lX2hhc2hWfFrh4LVtxwMKAG5ldHdvcmtfaWT7fKz1CgYAc3RhdGVzAQ4AaW5maW5pYnVybl9iaXQAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:soul_sand", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNvdWxfc2FuZAQJAG5hbWVfaGFzaMaf+bccu+KTAwoAbmV0d29ya19pZBQSHrMKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNvdWxfc2FuZAQJAG5hbWVfaGFzaMaf+bccu+KTAwoAbmV0d29ya19pZBQSHrMKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:magma", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTVAAAACAQAbmFtZQ8AbWluZWNyYWZ0Om1hZ21hBAkAbmFtZV9oYXNoqyTjKaIsWfYDCgBuZXR3b3JrX2lkyfWAZgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTVAAAACAQAbmFtZQ8AbWluZWNyYWZ0Om1hZ21hBAkAbmFtZV9oYXNoqyTjKaIsWfYDCgBuZXR3b3JrX2lkyfWAZgoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:nether_wart" }, { "id": "minecraft:end_stone", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR5AAAACAQAbmFtZRMAbWluZWNyYWZ0OmVuZF9zdG9uZQQJAG5hbWVfaGFzaH1J9jA39GJNAwoAbmV0d29ya19pZFeFQ7UKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR5AAAACAQAbmFtZRMAbWluZWNyYWZ0OmVuZF9zdG9uZQQJAG5hbWVfaGFzaH1J9jA39GJNAwoAbmV0d29ya19pZFeFQ7UKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:chorus_flower", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTIAAAACAQAbmFtZRcAbWluZWNyYWZ0OmNob3J1c19mbG93ZXIECQBuYW1lX2hhc2iMpSodli5uawMKAG5ldHdvcmtfaWRnd1ZWCgYAc3RhdGVzAwMAYWdlAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTIAAAACAQAbmFtZRcAbWluZWNyYWZ0OmNob3J1c19mbG93ZXIECQBuYW1lX2hhc2iMpSodli5uawMKAG5ldHdvcmtfaWRnd1ZWCgYAc3RhdGVzAwMAYWdlAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:chorus_plant", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTwAAAACAQAbmFtZRYAbWluZWNyYWZ0OmNob3J1c19wbGFudAQJAG5hbWVfaGFzaJhSrmNGKwaMAwoAbmV0d29ya19pZA3uVqMKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTwAAAACAQAbmFtZRYAbWluZWNyYWZ0OmNob3J1c19wbGFudAQJAG5hbWVfaGFzaJhSrmNGKwaMAwoAbmV0d29ya19pZA3uVqMKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:chorus_fruit" @@ -2926,79 +3147,79 @@ }, { "id": "minecraft:sponge", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAAAACAQAbmFtZRAAbWluZWNyYWZ0OnNwb25nZQQJAG5hbWVfaGFzaLrd2ScYRDMiAwoAbmV0d29ya19pZF01rO0KBgBzdGF0ZXMICwBzcG9uZ2VfdHlwZQMAZHJ5AAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAAAACAQAbmFtZRAAbWluZWNyYWZ0OnNwb25nZQQJAG5hbWVfaGFzaLrd2ScYRDMiAwoAbmV0d29ya19pZF01rO0KBgBzdGF0ZXMICwBzcG9uZ2VfdHlwZQMAZHJ5AAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:sponge", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAAAACAQAbmFtZRAAbWluZWNyYWZ0OnNwb25nZQQJAG5hbWVfaGFzaLrd2ScYRDMiAwoAbmV0d29ya19pZPiOc4QKBgBzdGF0ZXMICwBzcG9uZ2VfdHlwZQMAd2V0AAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAAAACAQAbmFtZRAAbWluZWNyYWZ0OnNwb25nZQQJAG5hbWVfaGFzaLrd2ScYRDMiAwoAbmV0d29ya19pZPiOc4QKBgBzdGF0ZXMICwBzcG9uZ2VfdHlwZQMAd2V0AAMHAHZlcnNpb24DABUBAA==" }, { - "id": "minecraft:coral_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkGnlaAwoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAQgAZGVhZF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + "id": "minecraft:tube_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRoAbWluZWNyYWZ0OnR1YmVfY29yYWxfYmxvY2sECQBuYW1lX2hhc2iGkaiR7Eot4wMKAG5ldHdvcmtfaWQPNJ6sCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { - "id": "minecraft:coral_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkSnHuagoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAQgAZGVhZF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + "id": "minecraft:brain_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRQBAAACAQAbmFtZRsAbWluZWNyYWZ0OmJyYWluX2NvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoeDNAK18yUo4DCgBuZXR3b3JrX2lkloN1vgoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { - "id": "minecraft:coral_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkmkHyegoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUBCABkZWFkX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "id": "minecraft:bubble_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRRBAAACAQAbmFtZRwAbWluZWNyYWZ0OmJ1YmJsZV9jb3JhbF9ibG9jawQJAG5hbWVfaGFzaAI2mwMlvcNbAwoAbmV0d29ya19pZBlkxKIKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { - "id": "minecraft:coral_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkdpUDxgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQBCABkZWFkX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "id": "minecraft:fire_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRSBAAACAQAbmFtZRoAbWluZWNyYWZ0OmZpcmVfY29yYWxfYmxvY2sECQBuYW1lX2hhc2gg1gLeXLmKaAMKAG5ldHdvcmtfaWSp3W57CgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { - "id": "minecraft:coral_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkYNWvYgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cBCABkZWFkX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "id": "minecraft:horn_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRTBAAACAQAbmFtZRoAbWluZWNyYWZ0Omhvcm5fY29yYWxfYmxvY2sECQBuYW1lX2hhc2hnZSLRWUwGhAMKAG5ldHdvcmtfaWRSK6ccCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { - "id": "minecraft:coral_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkZSxBQgoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABibHVlAQgAZGVhZF9iaXQBAAMHAHZlcnNpb24ERhQBAA==" + "id": "minecraft:dead_tube_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRUBAAACAQAbmFtZR8AbWluZWNyYWZ0OmRlYWRfdHViZV9jb3JhbF9ibG9jawQJAG5hbWVfaGFzaB9+lY3hAkNNAwoAbmV0d29ya19pZF0hKKYKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { - "id": "minecraft:coral_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lklSTVqQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBABwaW5rAQgAZGVhZF9iaXQBAAMHAHZlcnNpb24ERhQBAA==" + "id": "minecraft:dead_brain_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRVBAAACAQAbmFtZSAAbWluZWNyYWZ0OmRlYWRfYnJhaW5fY29yYWxfYmxvY2sECQBuYW1lX2hhc2iHyDn52AO8uwMKAG5ldHdvcmtfaWQw7yCaCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { - "id": "minecraft:coral_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lk5fTYuQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgBwdXJwbGUBCABkZWFkX2JpdAEAAwcAdmVyc2lvbgRGFAEA" + "id": "minecraft:dead_bubble_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRWBAAACAQAbmFtZSEAbWluZWNyYWZ0OmRlYWRfYnViYmxlX2NvcmFsX2Jsb2NrBAkAbmFtZV9oYXNotwkk/ITrsjADCgBuZXR3b3JrX2lk56mXUgoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { - "id": "minecraft:coral_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkwUjqBAoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yAwByZWQBCABkZWFkX2JpdAEAAwcAdmVyc2lvbgRGFAEA" + "id": "minecraft:dead_fire_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRXBAAACAQAbmFtZR8AbWluZWNyYWZ0OmRlYWRfZmlyZV9jb3JhbF9ibG9jawQJAG5hbWVfaGFzaG0qHxbIrBEyAwoAbmV0d29ya19pZFvnH88KBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { - "id": "minecraft:coral_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoxTOVIjqYOYIDCgBuZXR3b3JrX2lkq4iWoQoGAHN0YXRlcwgLAGNvcmFsX2NvbG9yBgB5ZWxsb3cBCABkZWFkX2JpdAEAAwcAdmVyc2lvbgRGFAEA" + "id": "minecraft:dead_horn_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRYBAAACAQAbmFtZR8AbWluZWNyYWZ0OmRlYWRfaG9ybl9jb3JhbF9ibG9jawQJAG5hbWVfaGFzaL7D8bu4Fm+0AwoAbmV0d29ya19pZEALRLoKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:sculk", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAgAACAQAbmFtZQ8AbWluZWNyYWZ0OnNjdWxrBAkAbmFtZV9oYXNo2Lq7T5yQF8kDCgBuZXR3b3JrX2lkyqUPPgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAgAACAQAbmFtZQ8AbWluZWNyYWZ0OnNjdWxrBAkAbmFtZV9oYXNo2Lq7T5yQF8kDCgBuZXR3b3JrX2lkyqUPPgoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:sculk_vein", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTKAgAACAQAbmFtZRQAbWluZWNyYWZ0OnNjdWxrX3ZlaW4ECQBuYW1lX2hhc2gJUdhVooV4zwMKAG5ldHdvcmtfaWSUfn1XCgYAc3RhdGVzAxkAbXVsdGlfZmFjZV9kaXJlY3Rpb25fYml0cwAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTKAgAACAQAbmFtZRQAbWluZWNyYWZ0OnNjdWxrX3ZlaW4ECQBuYW1lX2hhc2gJUdhVooV4zwMKAG5ldHdvcmtfaWSUfn1XCgYAc3RhdGVzAxkAbXVsdGlfZmFjZV9kaXJlY3Rpb25fYml0cwAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:sculk_catalyst", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAgAACAQAbmFtZRgAbWluZWNyYWZ0OnNjdWxrX2NhdGFseXN0BAkAbmFtZV9oYXNo+gCpbrCHST4DCgBuZXR3b3JrX2lkMJ2n/woGAHN0YXRlcwEFAGJsb29tAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAgAACAQAbmFtZRgAbWluZWNyYWZ0OnNjdWxrX2NhdGFseXN0BAkAbmFtZV9oYXNo+gCpbrCHST4DCgBuZXR3b3JrX2lkMJ2n/woGAHN0YXRlcwEFAGJsb29tAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:sculk_shrieker", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTMAgAACAQAbmFtZRgAbWluZWNyYWZ0OnNjdWxrX3Nocmlla2VyBAkAbmFtZV9oYXNo5OXtyObniQ4DCgBuZXR3b3JrX2lkxapoNAoGAHN0YXRlcwEGAGFjdGl2ZQABCgBjYW5fc3VtbW9uAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTMAgAACAQAbmFtZRgAbWluZWNyYWZ0OnNjdWxrX3Nocmlla2VyBAkAbmFtZV9oYXNo5OXtyObniQ4DCgBuZXR3b3JrX2lkxapoNAoGAHN0YXRlcwEGAGFjdGl2ZQABCgBjYW5fc3VtbW9uAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:sculk_sensor", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQyAgAACAQAbmFtZRYAbWluZWNyYWZ0OnNjdWxrX3NlbnNvcgQJAG5hbWVfaGFzaCkmHreeTgNnAwoAbmV0d29ya19pZLj2WPcKBgBzdGF0ZXMDEgBzY3Vsa19zZW5zb3JfcGhhc2UAAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQyAgAACAQAbmFtZRYAbWluZWNyYWZ0OnNjdWxrX3NlbnNvcgQJAG5hbWVfaGFzaCkmHreeTgNnAwoAbmV0d29ya19pZLj2WPcKBgBzdGF0ZXMDEgBzY3Vsa19zZW5zb3JfcGhhc2UAAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:calibrated_sculk_sensor", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRDAwAACAQAbmFtZSEAbWluZWNyYWZ0OmNhbGlicmF0ZWRfc2N1bGtfc2Vuc29yBAkAbmFtZV9oYXNoffAcXXN/iJUDCgBuZXR3b3JrX2lkwOx3QQoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAxIAc2N1bGtfc2Vuc29yX3BoYXNlAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRDAwAACAQAbmFtZSEAbWluZWNyYWZ0OmNhbGlicmF0ZWRfc2N1bGtfc2Vuc29yBAkAbmFtZV9oYXNoffAcXXN/iJUDCgBuZXR3b3JrX2lkwOx3QQoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAxIAc2N1bGtfc2Vuc29yX3BoYXNlAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:reinforced_deepslate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTRAgAACAQAbmFtZR4AbWluZWNyYWZ0OnJlaW5mb3JjZWRfZGVlcHNsYXRlBAkAbmFtZV9oYXNoldDmj91EapQDCgBuZXR3b3JrX2lkHIt+aQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTRAgAACAQAbmFtZR4AbWluZWNyYWZ0OnJlaW5mb3JjZWRfZGVlcHNsYXRlBAkAbmFtZV9oYXNoldDmj91EapQDCgBuZXR3b3JrX2lkHIt+aQoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:leather_helmet" @@ -3168,6 +3389,9 @@ { "id": "minecraft:crossbow" }, + { + "id": "minecraft:mace" + }, { "id": "minecraft:arrow" }, @@ -3323,6 +3547,41 @@ "id": "minecraft:arrow", "damage": 43 }, + { + "id": "minecraft:arrow", + "damage": 44 + }, + { + "id": "minecraft:arrow", + "damage": 45 + }, + { + "id": "minecraft:arrow", + "damage": 46 + }, + { + "id": "minecraft:arrow", + "damage": 47 + }, + { + "id": "minecraft:ominous_bottle" + }, + { + "id": "minecraft:ominous_bottle", + "damage": 1 + }, + { + "id": "minecraft:ominous_bottle", + "damage": 2 + }, + { + "id": "minecraft:ominous_bottle", + "damage": 3 + }, + { + "id": "minecraft:ominous_bottle", + "damage": 4 + }, { "id": "minecraft:shield" }, @@ -3386,6 +3645,9 @@ { "id": "minecraft:snowball" }, + { + "id": "minecraft:wind_charge" + }, { "id": "minecraft:shears" }, @@ -3457,6 +3719,9 @@ { "id": "minecraft:diamond_horse_armor" }, + { + "id": "minecraft:wolf_armor" + }, { "id": "minecraft:trident" }, @@ -3646,6 +3911,22 @@ "id": "minecraft:potion", "damage": 42 }, + { + "id": "minecraft:potion", + "damage": 43 + }, + { + "id": "minecraft:potion", + "damage": 44 + }, + { + "id": "minecraft:potion", + "damage": 45 + }, + { + "id": "minecraft:potion", + "damage": 46 + }, { "id": "minecraft:splash_potion" }, @@ -3817,6 +4098,22 @@ "id": "minecraft:splash_potion", "damage": 42 }, + { + "id": "minecraft:splash_potion", + "damage": 43 + }, + { + "id": "minecraft:splash_potion", + "damage": 44 + }, + { + "id": "minecraft:splash_potion", + "damage": 45 + }, + { + "id": "minecraft:splash_potion", + "damage": 46 + }, { "id": "minecraft:lingering_potion" }, @@ -3988,6 +4285,22 @@ "id": "minecraft:lingering_potion", "damage": 42 }, + { + "id": "minecraft:lingering_potion", + "damage": 43 + }, + { + "id": "minecraft:lingering_potion", + "damage": 44 + }, + { + "id": "minecraft:lingering_potion", + "damage": 45 + }, + { + "id": "minecraft:lingering_potion", + "damage": 46 + }, { "id": "minecraft:spyglass" }, @@ -4062,119 +4375,119 @@ }, { "id": "minecraft:torch", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQyAAAACAQAbmFtZQ8AbWluZWNyYWZ0OnRvcmNoBAkAbmFtZV9oYXNoagn7rmDBzisDCgBuZXR3b3JrX2lk+BwwuQoGAHN0YXRlcwgWAHRvcmNoX2ZhY2luZ19kaXJlY3Rpb24HAHVua25vd24AAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQyAAAACAQAbmFtZQ8AbWluZWNyYWZ0OnRvcmNoBAkAbmFtZV9oYXNoagn7rmDBzisDCgBuZXR3b3JrX2lk+BwwuQoGAHN0YXRlcwgWAHRvcmNoX2ZhY2luZ19kaXJlY3Rpb24HAHVua25vd24AAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:soul_torch", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQLAgAACAQAbmFtZRQAbWluZWNyYWZ0OnNvdWxfdG9yY2gECQBuYW1lX2hhc2huixOT04BRdQMKAG5ldHdvcmtfaWShbFILCgYAc3RhdGVzCBYAdG9yY2hfZmFjaW5nX2RpcmVjdGlvbgcAdW5rbm93bgADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQLAgAACAQAbmFtZRQAbWluZWNyYWZ0OnNvdWxfdG9yY2gECQBuYW1lX2hhc2huixOT04BRdQMKAG5ldHdvcmtfaWShbFILCgYAc3RhdGVzCBYAdG9yY2hfZmFjaW5nX2RpcmVjdGlvbgcAdW5rbm93bgADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:sea_pickle", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAQAACAQAbmFtZRQAbWluZWNyYWZ0OnNlYV9waWNrbGUECQBuYW1lX2hhc2iONEfZJB+glgMKAG5ldHdvcmtfaWSINWQyCgYAc3RhdGVzAw0AY2x1c3Rlcl9jb3VudAAAAAABCABkZWFkX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAQAACAQAbmFtZRQAbWluZWNyYWZ0OnNlYV9waWNrbGUECQBuYW1lX2hhc2iONEfZJB+glgMKAG5ldHdvcmtfaWSINWQyCgYAc3RhdGVzAw0AY2x1c3Rlcl9jb3VudAAAAAABCABkZWFkX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:lantern", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTPAQAACAQAbmFtZREAbWluZWNyYWZ0OmxhbnRlcm4ECQBuYW1lX2hhc2hMw44VI2HWygMKAG5ldHdvcmtfaWRkjQvzCgYAc3RhdGVzAQcAaGFuZ2luZwAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTPAQAACAQAbmFtZREAbWluZWNyYWZ0OmxhbnRlcm4ECQBuYW1lX2hhc2hMw44VI2HWygMKAG5ldHdvcmtfaWRkjQvzCgYAc3RhdGVzAQcAaGFuZ2luZwAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:soul_lantern", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQMAgAACAQAbmFtZRYAbWluZWNyYWZ0OnNvdWxfbGFudGVybgQJAG5hbWVfaGFzaGjIpjxk9z+RAwoAbmV0d29ya19pZGfoP8cKBgBzdGF0ZXMBBwBoYW5naW5nAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQMAgAACAQAbmFtZRYAbWluZWNyYWZ0OnNvdWxfbGFudGVybgQJAG5hbWVfaGFzaGjIpjxk9z+RAwoAbmV0d29ya19pZGfoP8cKBgBzdGF0ZXMBBwBoYW5naW5nAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:candle", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAgAACAQAbmFtZRAAbWluZWNyYWZ0OmNhbmRsZQQJAG5hbWVfaGFzaHPd+MsNdWTfAwoAbmV0d29ya19pZHsBMA0KBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAgAACAQAbmFtZRAAbWluZWNyYWZ0OmNhbmRsZQQJAG5hbWVfaGFzaHPd+MsNdWTfAwoAbmV0d29ya19pZHsBMA0KBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:white_candle", - "block_state_b64": "CgAAAwgAYmxvY2tfaWScAgAACAQAbmFtZRYAbWluZWNyYWZ0OndoaXRlX2NhbmRsZQQJAG5hbWVfaGFzaN1EG5Q1mHiEAwoAbmV0d29ya19pZKN1mmgKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWScAgAACAQAbmFtZRYAbWluZWNyYWZ0OndoaXRlX2NhbmRsZQQJAG5hbWVfaGFzaN1EG5Q1mHiEAwoAbmV0d29ya19pZKN1mmgKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:orange_candle", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSdAgAACAQAbmFtZRcAbWluZWNyYWZ0Om9yYW5nZV9jYW5kbGUECQBuYW1lX2hhc2jySEVWHgUIHQMKAG5ldHdvcmtfaWSfVz82CgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSdAgAACAQAbmFtZRcAbWluZWNyYWZ0Om9yYW5nZV9jYW5kbGUECQBuYW1lX2hhc2jySEVWHgUIHQMKAG5ldHdvcmtfaWSfVz82CgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:magenta_candle", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hZ2VudGFfY2FuZGxlBAkAbmFtZV9oYXNoG0u6YIOoBSEDCgBuZXR3b3JrX2lk9xGNkQoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hZ2VudGFfY2FuZGxlBAkAbmFtZV9oYXNoG0u6YIOoBSEDCgBuZXR3b3JrX2lk9xGNkQoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:light_blue_candle", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSfAgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY2FuZGxlBAkAbmFtZV9oYXNocXGeK0zgrG0DCgBuZXR3b3JrX2lk2m1y8goGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSfAgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY2FuZGxlBAkAbmFtZV9oYXNocXGeK0zgrG0DCgBuZXR3b3JrX2lk2m1y8goGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:yellow_candle", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSgAgAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19jYW5kbGUECQBuYW1lX2hhc2i00dtusU3CqQMKAG5ldHdvcmtfaWR9LTmpCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSgAgAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19jYW5kbGUECQBuYW1lX2hhc2i00dtusU3CqQMKAG5ldHdvcmtfaWR9LTmpCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:lime_candle", - "block_state_b64": "CgAAAwgAYmxvY2tfaWShAgAACAQAbmFtZRUAbWluZWNyYWZ0OmxpbWVfY2FuZGxlBAkAbmFtZV9oYXNokcmrw5xvz7ADCgBuZXR3b3JrX2lkIAUu6QoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAgAACAQAbmFtZRUAbWluZWNyYWZ0OmxpbWVfY2FuZGxlBAkAbmFtZV9oYXNokcmrw5xvz7ADCgBuZXR3b3JrX2lkIAUu6QoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:pink_candle", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAgAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfY2FuZGxlBAkAbmFtZV9oYXNoQJdEY4sZ0dwDCgBuZXR3b3JrX2lk23Rn5AoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAgAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfY2FuZGxlBAkAbmFtZV9oYXNoQJdEY4sZ0dwDCgBuZXR3b3JrX2lk23Rn5AoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:gray_candle", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSjAgAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXlfY2FuZGxlBAkAbmFtZV9oYXNoS5poSo9wBDEDCgBuZXR3b3JrX2lk3trRCAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSjAgAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXlfY2FuZGxlBAkAbmFtZV9oYXNoS5poSo9wBDEDCgBuZXR3b3JrX2lk3trRCAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:light_gray_candle", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY2FuZGxlBAkAbmFtZV9oYXNo9ruTZLBNMasDCgBuZXR3b3JrX2lkb6DOegoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY2FuZGxlBAkAbmFtZV9oYXNo9ruTZLBNMasDCgBuZXR3b3JrX2lkb6DOegoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:cyan_candle", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAgAACAQAbmFtZRUAbWluZWNyYWZ0OmN5YW5fY2FuZGxlBAkAbmFtZV9oYXNoc/M8PNVcjOwDCgBuZXR3b3JrX2lkZoIQOQoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAgAACAQAbmFtZRUAbWluZWNyYWZ0OmN5YW5fY2FuZGxlBAkAbmFtZV9oYXNoc/M8PNVcjOwDCgBuZXR3b3JrX2lkZoIQOQoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:purple_candle", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSmAgAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnBsZV9jYW5kbGUECQBuYW1lX2hhc2jaI3xUW0/myQMKAG5ldHdvcmtfaWSnLI2BCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSmAgAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnBsZV9jYW5kbGUECQBuYW1lX2hhc2jaI3xUW0/myQMKAG5ldHdvcmtfaWSnLI2BCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:blue_candle", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSnAgAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfY2FuZGxlBAkAbmFtZV9oYXNoAASSPW6TgQADCgBuZXR3b3JrX2lkrxrjQAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSnAgAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfY2FuZGxlBAkAbmFtZV9oYXNoAASSPW6TgQADCgBuZXR3b3JrX2lkrxrjQAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:brown_candle", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAgAACAQAbmFtZRYAbWluZWNyYWZ0OmJyb3duX2NhbmRsZQQJAG5hbWVfaGFzaDia0l6s1+WYAwoAbmV0d29ya19pZKSkBXYKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAgAACAQAbmFtZRYAbWluZWNyYWZ0OmJyb3duX2NhbmRsZQQJAG5hbWVfaGFzaDia0l6s1+WYAwoAbmV0d29ya19pZKSkBXYKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:green_candle", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAgAACAQAbmFtZRYAbWluZWNyYWZ0OmdyZWVuX2NhbmRsZQQJAG5hbWVfaGFzaLeFPO1l+fIoAwoAbmV0d29ya19pZBkznDsKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAgAACAQAbmFtZRYAbWluZWNyYWZ0OmdyZWVuX2NhbmRsZQQJAG5hbWVfaGFzaLeFPO1l+fIoAwoAbmV0d29ya19pZBkznDsKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:red_candle", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9jYW5kbGUECQBuYW1lX2hhc2jjAQpGf59ZdwMKAG5ldHdvcmtfaWRbb88GCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9jYW5kbGUECQBuYW1lX2hhc2jjAQpGf59ZdwMKAG5ldHdvcmtfaWRbb88GCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:black_candle", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAgAACAQAbmFtZRYAbWluZWNyYWZ0OmJsYWNrX2NhbmRsZQQJAG5hbWVfaGFzaB+wRDpOqREKAwoAbmV0d29ya19pZNnOnuEKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAgAACAQAbmFtZRYAbWluZWNyYWZ0OmJsYWNrX2NhbmRsZQQJAG5hbWVfaGFzaB+wRDpOqREKAwoAbmV0d29ya19pZNnOnuEKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:crafting_table", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ6AAAACAQAbmFtZRgAbWluZWNyYWZ0OmNyYWZ0aW5nX3RhYmxlBAkAbmFtZV9oYXNoe76VAmjvbpYDCgBuZXR3b3JrX2lkwCxwaAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ6AAAACAQAbmFtZRgAbWluZWNyYWZ0OmNyYWZ0aW5nX3RhYmxlBAkAbmFtZV9oYXNoe76VAmjvbpYDCgBuZXR3b3JrX2lkwCxwaAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:cartography_table", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTHAQAACAQAbmFtZRsAbWluZWNyYWZ0OmNhcnRvZ3JhcGh5X3RhYmxlBAkAbmFtZV9oYXNomaWiiD/znP8DCgBuZXR3b3JrX2lkI6FzMwoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTHAQAACAQAbmFtZRsAbWluZWNyYWZ0OmNhcnRvZ3JhcGh5X3RhYmxlBAkAbmFtZV9oYXNomaWiiD/znP8DCgBuZXR3b3JrX2lkI6FzMwoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:fletching_table", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTIAQAACAQAbmFtZRkAbWluZWNyYWZ0OmZsZXRjaGluZ190YWJsZQQJAG5hbWVfaGFzaPFibh8unKyUAwoAbmV0d29ya19pZJ2mW0oKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTIAQAACAQAbmFtZRkAbWluZWNyYWZ0OmZsZXRjaGluZ190YWJsZQQJAG5hbWVfaGFzaPFibh8unKyUAwoAbmV0d29ya19pZJ2mW0oKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:smithing_table", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAQAACAQAbmFtZRgAbWluZWNyYWZ0OnNtaXRoaW5nX3RhYmxlBAkAbmFtZV9oYXNo4tFES2xOXEYDCgBuZXR3b3JrX2lkXWMBzQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAQAACAQAbmFtZRgAbWluZWNyYWZ0OnNtaXRoaW5nX3RhYmxlBAkAbmFtZV9oYXNo4tFES2xOXEYDCgBuZXR3b3JrX2lkXWMBzQoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:beehive", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAQAACAQAbmFtZREAbWluZWNyYWZ0OmJlZWhpdmUECQBuYW1lX2hhc2hCcqn12UbNpwMKAG5ldHdvcmtfaWR/idcaCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAMLAGhvbmV5X2xldmVsAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAQAACAQAbmFtZREAbWluZWNyYWZ0OmJlZWhpdmUECQBuYW1lX2hhc2hCcqn12UbNpwMKAG5ldHdvcmtfaWR/idcaCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAMLAGhvbmV5X2xldmVsAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:suspicious_sand", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQQAwAACAQAbmFtZRkAbWluZWNyYWZ0OnN1c3BpY2lvdXNfc2FuZAQJAG5hbWVfaGFzaL67QsuvLP00AwoAbmV0d29ya19pZKnkaIAKBgBzdGF0ZXMDEABicnVzaGVkX3Byb2dyZXNzAAAAAAEHAGhhbmdpbmcBAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQQAwAACAQAbmFtZRkAbWluZWNyYWZ0OnN1c3BpY2lvdXNfc2FuZAQJAG5hbWVfaGFzaL67QsuvLP00AwoAbmV0d29ya19pZKnkaIAKBgBzdGF0ZXMDEABicnVzaGVkX3Byb2dyZXNzAAAAAAEHAGhhbmdpbmcBAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:suspicious_gravel", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ8AwAACAQAbmFtZRsAbWluZWNyYWZ0OnN1c3BpY2lvdXNfZ3JhdmVsBAkAbmFtZV9oYXNoJSVbGNk7C3oDCgBuZXR3b3JrX2lkvIEJAAoGAHN0YXRlcwMQAGJydXNoZWRfcHJvZ3Jlc3MAAAAAAQcAaGFuZ2luZwEAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ8AwAACAQAbmFtZRsAbWluZWNyYWZ0OnN1c3BpY2lvdXNfZ3JhdmVsBAkAbmFtZV9oYXNoJSVbGNk7C3oDCgBuZXR3b3JrX2lkvIEJAAoGAHN0YXRlcwMQAGJydXNoZWRfcHJvZ3Jlc3MAAAAAAQcAaGFuZ2luZwEAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:campfire" @@ -4184,156 +4497,156 @@ }, { "id": "minecraft:furnace", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ9AAAACAQAbmFtZREAbWluZWNyYWZ0OmZ1cm5hY2UECQBuYW1lX2hhc2ioOQrludYY8wMKAG5ldHdvcmtfaWRZxnDOCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ9AAAACAQAbmFtZREAbWluZWNyYWZ0OmZ1cm5hY2UECQBuYW1lX2hhc2ioOQrludYY8wMKAG5ldHdvcmtfaWRZxnDOCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:blast_furnace", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTDAQAACAQAbmFtZRcAbWluZWNyYWZ0OmJsYXN0X2Z1cm5hY2UECQBuYW1lX2hhc2ivDbnjkpGm5QMKAG5ldHdvcmtfaWTcEbV/CgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTDAQAACAQAbmFtZRcAbWluZWNyYWZ0OmJsYXN0X2Z1cm5hY2UECQBuYW1lX2hhc2ivDbnjkpGm5QMKAG5ldHdvcmtfaWTcEbV/CgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:smoker", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTFAQAACAQAbmFtZRAAbWluZWNyYWZ0OnNtb2tlcgQJAG5hbWVfaGFzaJd1rDMkRWomAwoAbmV0d29ya19pZGWswMwKBgBzdGF0ZXMIHABtaW5lY3JhZnQ6Y2FyZGluYWxfZGlyZWN0aW9uBQBzb3V0aAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTFAQAACAQAbmFtZRAAbWluZWNyYWZ0OnNtb2tlcgQJAG5hbWVfaGFzaJd1rDMkRWomAwoAbmV0d29ya19pZGWswMwKBgBzdGF0ZXMIHABtaW5lY3JhZnQ6Y2FyZGluYWxfZGlyZWN0aW9uBQBzb3V0aAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:respawn_anchor", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQPAgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlc3Bhd25fYW5jaG9yBAkAbmFtZV9oYXNoZOdcjW05qigDCgBuZXR3b3JrX2lkmhMcaQoGAHN0YXRlcwMVAHJlc3Bhd25fYW5jaG9yX2NoYXJnZQAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQPAgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlc3Bhd25fYW5jaG9yBAkAbmFtZV9oYXNoZOdcjW05qigDCgBuZXR3b3JrX2lkmhMcaQoGAHN0YXRlcwMVAHJlc3Bhd25fYW5jaG9yX2NoYXJnZQAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:brewing_stand" }, { "id": "minecraft:anvil", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lk8Z3VowoGAHN0YXRlcwgGAGRhbWFnZQkAdW5kYW1hZ2VkCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lk8Z3VowoGAHN0YXRlcwgGAGRhbWFnZQkAdW5kYW1hZ2VkCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:anvil", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lkpiv8BAoGAHN0YXRlcwgGAGRhbWFnZRAAc2xpZ2h0bHlfZGFtYWdlZAgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lkpiv8BAoGAHN0YXRlcwgGAGRhbWFnZRAAc2xpZ2h0bHlfZGFtYWdlZAgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:anvil", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lkFu+pdwoGAHN0YXRlcwgGAGRhbWFnZQwAdmVyeV9kYW1hZ2VkCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lkFu+pdwoGAHN0YXRlcwgGAGRhbWFnZQwAdmVyeV9kYW1hZ2VkCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:grindstone", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTCAQAACAQAbmFtZRQAbWluZWNyYWZ0OmdyaW5kc3RvbmUECQBuYW1lX2hhc2id56zc0nk99wMKAG5ldHdvcmtfaWS4Es07CgYAc3RhdGVzCAoAYXR0YWNobWVudAgAc3RhbmRpbmcDCQBkaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTCAQAACAQAbmFtZRQAbWluZWNyYWZ0OmdyaW5kc3RvbmUECQBuYW1lX2hhc2id56zc0nk99wMKAG5ldHdvcmtfaWS4Es07CgYAc3RhdGVzCAoAYXR0YWNobWVudAgAc3RhbmRpbmcDCQBkaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:enchanting_table", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR0AAAACAQAbmFtZRoAbWluZWNyYWZ0OmVuY2hhbnRpbmdfdGFibGUECQBuYW1lX2hhc2jgIx24VLvMvwMKAG5ldHdvcmtfaWRliFFJCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR0AAAACAQAbmFtZRoAbWluZWNyYWZ0OmVuY2hhbnRpbmdfdGFibGUECQBuYW1lX2hhc2jgIx24VLvMvwMKAG5ldHdvcmtfaWRliFFJCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:bookshelf", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQvAAAACAQAbmFtZRMAbWluZWNyYWZ0OmJvb2tzaGVsZgQJAG5hbWVfaGFzaDU04DrgJCS9AwoAbmV0d29ya19pZBcWwIwKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQvAAAACAQAbmFtZRMAbWluZWNyYWZ0OmJvb2tzaGVsZgQJAG5hbWVfaGFzaDU04DrgJCS9AwoAbmV0d29ya19pZBcWwIwKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:chiseled_bookshelf", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQNAwAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX2Jvb2tzaGVsZgQJAG5hbWVfaGFzaNXDBnsIsywYAwoAbmV0d29ya19pZIprt5IKBgBzdGF0ZXMDDABib29rc19zdG9yZWQAAAAAAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQNAwAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX2Jvb2tzaGVsZgQJAG5hbWVfaGFzaNXDBnsIsywYAwoAbmV0d29ya19pZIprt5IKBgBzdGF0ZXMDDABib29rc19zdG9yZWQAAAAAAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:lectern", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTBAQAACAQAbmFtZREAbWluZWNyYWZ0OmxlY3Rlcm4ECQBuYW1lX2hhc2j5Z4Mmi/1QxAMKAG5ldHdvcmtfaWR4JfDHCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgBCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTBAQAACAQAbmFtZREAbWluZWNyYWZ0OmxlY3Rlcm4ECQBuYW1lX2hhc2j5Z4Mmi/1QxAMKAG5ldHdvcmtfaWR4JfDHCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgBCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:cauldron" }, { "id": "minecraft:composter", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTUAQAACAQAbmFtZRMAbWluZWNyYWZ0OmNvbXBvc3RlcgQJAG5hbWVfaGFzaPAADHptzeWJAwoAbmV0d29ya19pZHIL6i4KBgBzdGF0ZXMDFABjb21wb3N0ZXJfZmlsbF9sZXZlbAAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTUAQAACAQAbmFtZRMAbWluZWNyYWZ0OmNvbXBvc3RlcgQJAG5hbWVfaGFzaPAADHptzeWJAwoAbmV0d29ya19pZHIL6i4KBgBzdGF0ZXMDFABjb21wb3N0ZXJfZmlsbF9sZXZlbAAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:chest", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ2AAAACAQAbmFtZQ8AbWluZWNyYWZ0OmNoZXN0BAkAbmFtZV9oYXNog9ozMxlcA88DCgBuZXR3b3JrX2lkDkOFvAoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ2AAAACAQAbmFtZQ8AbWluZWNyYWZ0OmNoZXN0BAkAbmFtZV9oYXNog9ozMxlcA88DCgBuZXR3b3JrX2lkDkOFvAoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:trapped_chest", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSSAAAACAQAbmFtZRcAbWluZWNyYWZ0OnRyYXBwZWRfY2hlc3QECQBuYW1lX2hhc2g2qpF9stsEjgMKAG5ldHdvcmtfaWTjJWYxCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAbm9ydGgAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSSAAAACAQAbmFtZRcAbWluZWNyYWZ0OnRyYXBwZWRfY2hlc3QECQBuYW1lX2hhc2g2qpF9stsEjgMKAG5ldHdvcmtfaWTjJWYxCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAbm9ydGgAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:ender_chest", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAAAACAQAbmFtZRUAbWluZWNyYWZ0OmVuZGVyX2NoZXN0BAkAbmFtZV9oYXNohEZzOFdg0WUDCgBuZXR3b3JrX2lkx4jiSQoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAAAACAQAbmFtZRUAbWluZWNyYWZ0OmVuZGVyX2NoZXN0BAkAbmFtZV9oYXNohEZzOFdg0WUDCgBuZXR3b3JrX2lkx4jiSQoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:barrel", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTKAQAACAQAbmFtZRAAbWluZWNyYWZ0OmJhcnJlbAQJAG5hbWVfaGFzaHDkRPGymiRqAwoAbmV0d29ya19pZPnxzgsKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTKAQAACAQAbmFtZRAAbWluZWNyYWZ0OmJhcnJlbAQJAG5hbWVfaGFzaHDkRPGymiRqAwoAbmV0d29ya19pZPnxzgsKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:undyed_shulker_box", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTNAAAACAQAbmFtZRwAbWluZWNyYWZ0OnVuZHllZF9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaOC9mypm/MlBAwoAbmV0d29ya19pZJ8rxp0KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTNAAAACAQAbmFtZRwAbWluZWNyYWZ0OnVuZHllZF9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaOC9mypm/MlBAwoAbmV0d29ya19pZJ8rxp0KBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:white_shulker_box", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAAAACAQAbmFtZRsAbWluZWNyYWZ0OndoaXRlX3NodWxrZXJfYm94BAkAbmFtZV9oYXNosK79m1rPUBwDCgBuZXR3b3JrX2lkjrET6goGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAAAACAQAbmFtZRsAbWluZWNyYWZ0OndoaXRlX3NodWxrZXJfYm94BAkAbmFtZV9oYXNosK79m1rPUBwDCgBuZXR3b3JrX2lkjrET6goGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:light_gray_shulker_box", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRrAwAACAQAbmFtZSAAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2iBe5zq7PxHmgMKAG5ldHdvcmtfaWSCVJv0CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRrAwAACAQAbmFtZSAAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2iBe5zq7PxHmgMKAG5ldHdvcmtfaWSCVJv0CgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:gray_shulker_box", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRqAwAACAQAbmFtZRoAbWluZWNyYWZ0OmdyYXlfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2ga2s8ctjHUhgMKAG5ldHdvcmtfaWS3WMsWCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRqAwAACAQAbmFtZRoAbWluZWNyYWZ0OmdyYXlfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2ga2s8ctjHUhgMKAG5ldHdvcmtfaWS3WMsWCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:black_shulker_box", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRyAwAACAQAbmFtZRsAbWluZWNyYWZ0OmJsYWNrX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoPm03OZphrp8DCgBuZXR3b3JrX2lkXHztNAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRyAwAACAQAbmFtZRsAbWluZWNyYWZ0OmJsYWNrX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoPm03OZphrp8DCgBuZXR3b3JrX2lkXHztNAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:brown_shulker_box", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRvAwAACAQAbmFtZRsAbWluZWNyYWZ0OmJyb3duX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoT3DD6qAL9cADCgBuZXR3b3JrX2lkaXxpYQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRvAwAACAQAbmFtZRsAbWluZWNyYWZ0OmJyb3duX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoT3DD6qAL9cADCgBuZXR3b3JrX2lkaXxpYQoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:red_shulker_box", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRxAwAACAQAbmFtZRkAbWluZWNyYWZ0OnJlZF9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaMIlKSCzqSZoAwoAbmV0d29ya19pZNrf+icKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRxAwAACAQAbmFtZRkAbWluZWNyYWZ0OnJlZF9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaMIlKSCzqSZoAwoAbmV0d29ya19pZNrf+icKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:orange_shulker_box", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRkAwAACAQAbmFtZRwAbWluZWNyYWZ0Om9yYW5nZV9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaG2MAXU67wGrAwoAbmV0d29ya19pZGoO05gKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRkAwAACAQAbmFtZRwAbWluZWNyYWZ0Om9yYW5nZV9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaG2MAXU67wGrAwoAbmV0d29ya19pZGoO05gKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:yellow_shulker_box", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRnAwAACAQAbmFtZRwAbWluZWNyYWZ0OnllbGxvd19zaHVsa2VyX2JveAQJAG5hbWVfaGFzaIsLwQHYjcIEAwoAbmV0d29ya19pZBCBSiYKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRnAwAACAQAbmFtZRwAbWluZWNyYWZ0OnllbGxvd19zaHVsa2VyX2JveAQJAG5hbWVfaGFzaIsLwQHYjcIEAwoAbmV0d29ya19pZBCBSiYKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:lime_shulker_box", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRoAwAACAQAbmFtZRoAbWluZWNyYWZ0OmxpbWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2hUwBkg+faUGAMKAG5ldHdvcmtfaWRJeKqqCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRoAwAACAQAbmFtZRoAbWluZWNyYWZ0OmxpbWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2hUwBkg+faUGAMKAG5ldHdvcmtfaWRJeKqqCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:green_shulker_box", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRwAwAACAQAbmFtZRsAbWluZWNyYWZ0OmdyZWVuX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoZgUeT3LupLUDCgBuZXR3b3JrX2lkzJiohQoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRwAwAACAQAbmFtZRsAbWluZWNyYWZ0OmdyZWVuX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoZgUeT3LupLUDCgBuZXR3b3JrX2lkzJiohQoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:cyan_shulker_box", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRsAwAACAQAbmFtZRoAbWluZWNyYWZ0OmN5YW5fc2h1bGtlcl9ib3gECQBuYW1lX2hhc2gSfbjteXg5yAMKAG5ldHdvcmtfaWTHeliECgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRsAwAACAQAbmFtZRoAbWluZWNyYWZ0OmN5YW5fc2h1bGtlcl9ib3gECQBuYW1lX2hhc2gSfbjteXg5yAMKAG5ldHdvcmtfaWTHeliECgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:light_blue_shulker_box", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRmAwAACAQAbmFtZSAAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2h0VFCX0qsRxQMKAG5ldHdvcmtfaWQXD8U0CgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRmAwAACAQAbmFtZSAAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2h0VFCX0qsRxQMKAG5ldHdvcmtfaWQXD8U0CgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:blue_shulker_box", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRuAwAACAQAbmFtZRoAbWluZWNyYWZ0OmJsdWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2hn9gS0XIe6rAMKAG5ldHdvcmtfaWTO4PJaCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRuAwAACAQAbmFtZRoAbWluZWNyYWZ0OmJsdWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2hn9gS0XIe6rAMKAG5ldHdvcmtfaWTO4PJaCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:purple_shulker_box", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRtAwAACAQAbmFtZRwAbWluZWNyYWZ0OnB1cnBsZV9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaEV/lkNPxRDdAwoAbmV0d29ya19pZFK25GAKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRtAwAACAQAbmFtZRwAbWluZWNyYWZ0OnB1cnBsZV9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaEV/lkNPxRDdAwoAbmV0d29ya19pZFK25GAKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:magenta_shulker_box", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRlAwAACAQAbmFtZR0AbWluZWNyYWZ0Om1hZ2VudGFfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2iqWM7IJHxcFgMKAG5ldHdvcmtfaWTyyudTCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRlAwAACAQAbmFtZR0AbWluZWNyYWZ0Om1hZ2VudGFfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2iqWM7IJHxcFgMKAG5ldHdvcmtfaWTyyudTCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:pink_shulker_box", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRpAwAACAQAbmFtZRoAbWluZWNyYWZ0OnBpbmtfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2in1tkJ1GNcZgMKAG5ldHdvcmtfaWQOEGXjCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRpAwAACAQAbmFtZRoAbWluZWNyYWZ0OnBpbmtfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2in1tkJ1GNcZgMKAG5ldHdvcmtfaWQOEGXjCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:armor_stand" }, { "id": "minecraft:noteblock", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQZAAAACAQAbmFtZRMAbWluZWNyYWZ0Om5vdGVibG9jawQJAG5hbWVfaGFzaHPA8dBBH0UaAwoAbmV0d29ya19pZH1U5QkKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQZAAAACAQAbmFtZRMAbWluZWNyYWZ0Om5vdGVibG9jawQJAG5hbWVfaGFzaHPA8dBBH0UaAwoAbmV0d29ya19pZH1U5QkKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:jukebox", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRUAAAACAQAbmFtZREAbWluZWNyYWZ0Omp1a2Vib3gECQBuYW1lX2hhc2ieAIPExf/ZfgMKAG5ldHdvcmtfaWSmR7JfCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRUAAAACAQAbmFtZREAbWluZWNyYWZ0Omp1a2Vib3gECQBuYW1lX2hhc2ieAIPExf/ZfgMKAG5ldHdvcmtfaWSmR7JfCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:music_disc_13" @@ -4383,6 +4696,15 @@ { "id": "minecraft:music_disc_relic" }, + { + "id": "minecraft:music_disc_creator" + }, + { + "id": "minecraft:music_disc_creator_music_box" + }, + { + "id": "minecraft:music_disc_precipice" + }, { "id": "minecraft:disc_fragment_5" }, @@ -4391,15 +4713,15 @@ }, { "id": "minecraft:glowstone", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRZAAAACAQAbmFtZRMAbWluZWNyYWZ0Omdsb3dzdG9uZQQJAG5hbWVfaGFzaFYqXNkefIlPAwoAbmV0d29ya19pZGT7WYYKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRZAAAACAQAbmFtZRMAbWluZWNyYWZ0Omdsb3dzdG9uZQQJAG5hbWVfaGFzaFYqXNkefIlPAwoAbmV0d29ya19pZGT7WYYKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:redstone_lamp", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR7AAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZHN0b25lX2xhbXAECQBuYW1lX2hhc2hJ9V80caPvEgMKAG5ldHdvcmtfaWRvNPwnCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR7AAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZHN0b25lX2xhbXAECQBuYW1lX2hhc2hJ9V80caPvEgMKAG5ldHdvcmtfaWRvNPwnCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:sea_lantern", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAAAACAQAbmFtZRUAbWluZWNyYWZ0OnNlYV9sYW50ZXJuBAkAbmFtZV9oYXNoLPsv1TX9M+QDCgBuZXR3b3JrX2lk1PPVyAoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAAAACAQAbmFtZRUAbWluZWNyYWZ0OnNlYV9sYW50ZXJuBAkAbmFtZV9oYXNoLPsv1TX9M+QDCgBuZXR3b3JrX2lk1PPVyAoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:oak_sign" @@ -4547,19 +4869,19 @@ }, { "id": "minecraft:beacon", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAAAACAQAbmFtZRAAbWluZWNyYWZ0OmJlYWNvbgQJAG5hbWVfaGFzaACwhhfSkdkHAwoAbmV0d29ya19pZF8jfiEKBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAAAACAQAbmFtZRAAbWluZWNyYWZ0OmJlYWNvbgQJAG5hbWVfaGFzaACwhhfSkdkHAwoAbmV0d29ya19pZF8jfiEKBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:bell", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTNAQAACAQAbmFtZQ4AbWluZWNyYWZ0OmJlbGwECQBuYW1lX2hhc2iPqsgDXRcsxAMKAG5ldHdvcmtfaWT7zhOoCgYAc3RhdGVzCAoAYXR0YWNobWVudAgAc3RhbmRpbmcDCQBkaXJlY3Rpb24AAAAAAQoAdG9nZ2xlX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTNAQAACAQAbmFtZQ4AbWluZWNyYWZ0OmJlbGwECQBuYW1lX2hhc2iPqsgDXRcsxAMKAG5ldHdvcmtfaWT7zhOoCgYAc3RhdGVzCAoAYXR0YWNobWVudAgAc3RhbmRpbmcDCQBkaXJlY3Rpb24AAAAAAQoAdG9nZ2xlX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:conduit", - "block_state_b64": "CgAAAwgAYmxvY2tfaWScAQAACAQAbmFtZREAbWluZWNyYWZ0OmNvbmR1aXQECQBuYW1lX2hhc2jqxKAxq2EaWQMKAG5ldHdvcmtfaWTWcBVnCgYAc3RhdGVzAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWScAQAACAQAbmFtZREAbWluZWNyYWZ0OmNvbmR1aXQECQBuYW1lX2hhc2jqxKAxq2EaWQMKAG5ldHdvcmtfaWTWcBVnCgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:stonecutter_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTEAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lY3V0dGVyX2Jsb2NrBAkAbmFtZV9oYXNoQAXTbAM3MeYDCgBuZXR3b3JrX2lkWS4RjAoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTEAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lY3V0dGVyX2Jsb2NrBAkAbmFtZV9oYXNoQAXTbAM3MeYDCgBuZXR3b3JrX2lkWS4RjAoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:coal" @@ -4633,6 +4955,9 @@ { "id": "minecraft:turtle_scute" }, + { + "id": "minecraft:armadillo_scute" + }, { "id": "minecraft:phantom_membrane" }, @@ -4663,6 +4988,13 @@ { "id": "minecraft:blaze_rod" }, + { + "id": "minecraft:breeze_rod" + }, + { + "id": "minecraft:heavy_core", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ7AgAACAQAbmFtZRQAbWluZWNyYWZ0OmhlYXZ5X2NvcmUECQBuYW1lX2hhc2hhz/uNCtrC2QMKAG5ldHdvcmtfaWRaFu+8CgYAc3RhdGVzAAMHAHZlcnNpb24DABUBAA==" + }, { "id": "minecraft:blaze_powder" }, @@ -4698,11 +5030,11 @@ }, { "id": "minecraft:end_rod", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTQAAAACAQAbmFtZREAbWluZWNyYWZ0OmVuZF9yb2QECQBuYW1lX2hhc2jx/q5cEA0hmQMKAG5ldHdvcmtfaWQ2eM8kCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTQAAAACAQAbmFtZREAbWluZWNyYWZ0OmVuZF9yb2QECQBuYW1lX2hhc2jx/q5cEA0hmQMKAG5ldHdvcmtfaWQ2eM8kCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:lightning_rod", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQ3AgAACAQAbmFtZRcAbWluZWNyYWZ0OmxpZ2h0bmluZ19yb2QECQBuYW1lX2hhc2ioXQF1xvfHNQMKAG5ldHdvcmtfaWRLuHyACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ3AgAACAQAbmFtZRcAbWluZWNyYWZ0OmxpZ2h0bmluZ19yb2QECQBuYW1lX2hhc2ioXQF1xvfHNQMKAG5ldHdvcmtfaWRLuHyACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:end_crystal" @@ -4716,6 +5048,9 @@ { "id": "minecraft:writable_book" }, + { + "id": "minecraft:trial_key" + }, { "id": "minecraft:enchanted_book", "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAEAAAA=" @@ -5156,6 +5491,54 @@ "id": "minecraft:enchanted_book", "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQlAAIDAGx2bAMAAAA=" }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQmAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQmAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQmAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQnAAIDAGx2bAEAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQnAAIDAGx2bAIAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQnAAIDAGx2bAMAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQnAAIDAGx2bAQAAAA=" + }, + { + "id": "minecraft:enchanted_book", + "nbt_b64": "CgAACQQAZW5jaAoBAAAAAgIAaWQnAAIDAGx2bAUAAAA=" + }, + { + "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": "CgAACQQAZW5jaAoBAAAAAgIAaWQoAAIDAGx2bAQAAAA=" + }, { "id": "minecraft:oak_boat" }, @@ -5212,19 +5595,19 @@ }, { "id": "minecraft:rail", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRCAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnJhaWwECQBuYW1lX2hhc2hUzmhUXYJDUQMKAG5ldHdvcmtfaWR+Sp6YCgYAc3RhdGVzAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRCAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnJhaWwECQBuYW1lX2hhc2hUzmhUXYJDUQMKAG5ldHdvcmtfaWR+Sp6YCgYAc3RhdGVzAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:golden_rail", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQbAAAACAQAbmFtZRUAbWluZWNyYWZ0OmdvbGRlbl9yYWlsBAkAbmFtZV9oYXNoOoV5MaKipoUDCgBuZXR3b3JrX2lkfAcxLwoGAHN0YXRlcwENAHJhaWxfZGF0YV9iaXQAAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQbAAAACAQAbmFtZRUAbWluZWNyYWZ0OmdvbGRlbl9yYWlsBAkAbmFtZV9oYXNoOoV5MaKipoUDCgBuZXR3b3JrX2lkfAcxLwoGAHN0YXRlcwENAHJhaWxfZGF0YV9iaXQAAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:detector_rail", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQcAAAACAQAbmFtZRcAbWluZWNyYWZ0OmRldGVjdG9yX3JhaWwECQBuYW1lX2hhc2gVUk31qOysUQMKAG5ldHdvcmtfaWRVW/aICgYAc3RhdGVzAQ0AcmFpbF9kYXRhX2JpdAADDgByYWlsX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQcAAAACAQAbmFtZRcAbWluZWNyYWZ0OmRldGVjdG9yX3JhaWwECQBuYW1lX2hhc2gVUk31qOysUQMKAG5ldHdvcmtfaWRVW/aICgYAc3RhdGVzAQ0AcmFpbF9kYXRhX2JpdAADDgByYWlsX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:activator_rail", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR+AAAACAQAbmFtZRgAbWluZWNyYWZ0OmFjdGl2YXRvcl9yYWlsBAkAbmFtZV9oYXNosIL91qriCRkDCgBuZXR3b3JrX2lkZfckmwoGAHN0YXRlcwENAHJhaWxfZGF0YV9iaXQAAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR+AAAACAQAbmFtZRgAbWluZWNyYWZ0OmFjdGl2YXRvcl9yYWlsBAkAbmFtZV9oYXNosIL91qriCRkDCgBuZXR3b3JrX2lkZfckmwoGAHN0YXRlcwENAHJhaWxfZGF0YV9iaXQAAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:minecart" @@ -5243,139 +5626,139 @@ }, { "id": "minecraft:redstone_block", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSYAAAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZHN0b25lX2Jsb2NrBAkAbmFtZV9oYXNoRhULL0r8o0sDCgBuZXR3b3JrX2lklayOHgoGAHN0YXRlcwADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSYAAAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZHN0b25lX2Jsb2NrBAkAbmFtZV9oYXNoRhULL0r8o0sDCgBuZXR3b3JrX2lklayOHgoGAHN0YXRlcwADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:redstone_torch", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRMAAAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZHN0b25lX3RvcmNoBAkAbmFtZV9oYXNoizFRjpYMIDgDCgBuZXR3b3JrX2lkuHz7yAoGAHN0YXRlcwgWAHRvcmNoX2ZhY2luZ19kaXJlY3Rpb24HAHVua25vd24AAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRMAAAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZHN0b25lX3RvcmNoBAkAbmFtZV9oYXNoizFRjpYMIDgDCgBuZXR3b3JrX2lkuHz7yAoGAHN0YXRlcwgWAHRvcmNoX2ZhY2luZ19kaXJlY3Rpb24HAHVua25vd24AAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:lever", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRFAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmxldmVyBAkAbmFtZV9oYXNoGMJeLJsUMLYDCgBuZXR3b3JrX2lkEF/GuAoGAHN0YXRlcwgPAGxldmVyX2RpcmVjdGlvbg4AZG93bl9lYXN0X3dlc3QBCABvcGVuX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRFAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmxldmVyBAkAbmFtZV9oYXNoGMJeLJsUMLYDCgBuZXR3b3JrX2lkEF/GuAoGAHN0YXRlcwgPAGxldmVyX2RpcmVjdGlvbg4AZG93bl9lYXN0X3dlc3QBCABvcGVuX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:wooden_button", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAAAACAQAbmFtZRcAbWluZWNyYWZ0Ondvb2Rlbl9idXR0b24ECQBuYW1lX2hhc2hR7PgSTQt0sQMKAG5ldHdvcmtfaWSU07kYCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAAAACAQAbmFtZRcAbWluZWNyYWZ0Ondvb2Rlbl9idXR0b24ECQBuYW1lX2hhc2hR7PgSTQt0sQMKAG5ldHdvcmtfaWSU07kYCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:spruce_button", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAQAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9idXR0b24ECQBuYW1lX2hhc2jBW9Z8aYE7YQMKAG5ldHdvcmtfaWTkUIGuCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAQAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9idXR0b24ECQBuYW1lX2hhc2jBW9Z8aYE7YQMKAG5ldHdvcmtfaWTkUIGuCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:birch_button", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSMAQAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX2J1dHRvbgQJAG5hbWVfaGFzaJXYgGuSHbTwAwoAbmV0d29ya19pZGWp3yoKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSMAQAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX2J1dHRvbgQJAG5hbWVfaGFzaJXYgGuSHbTwAwoAbmV0d29ya19pZGWp3yoKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:jungle_button", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSOAQAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9idXR0b24ECQBuYW1lX2hhc2iCgNANcJs+BQMKAG5ldHdvcmtfaWT9fImWCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSOAQAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9idXR0b24ECQBuYW1lX2hhc2iCgNANcJs+BQMKAG5ldHdvcmtfaWT9fImWCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:acacia_button", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAQAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9idXR0b24ECQBuYW1lX2hhc2gVvmcT7LTO0wMKAG5ldHdvcmtfaWRQnxIJCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAQAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9idXR0b24ECQBuYW1lX2hhc2gVvmcT7LTO0wMKAG5ldHdvcmtfaWRQnxIJCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:dark_oak_button", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSNAQAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX2J1dHRvbgQJAG5hbWVfaGFzaIV10ZGGrCIEAwoAbmV0d29ya19pZN5vAmIKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSNAQAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX2J1dHRvbgQJAG5hbWVfaGFzaIV10ZGGrCIEAwoAbmV0d29ya19pZN5vAmIKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:mangrove_button", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTmAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX2J1dHRvbgQJAG5hbWVfaGFzaNzeYYKLgOzJAwoAbmV0d29ya19pZAFEGQ0KBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTmAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX2J1dHRvbgQJAG5hbWVfaGFzaNzeYYKLgOzJAwoAbmV0d29ya19pZAFEGQ0KBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:cherry_button", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQRAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9idXR0b24ECQBuYW1lX2hhc2j2/IHjeAbUcwMKAG5ldHdvcmtfaWRJ1irQCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQRAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9idXR0b24ECQBuYW1lX2hhc2j2/IHjeAbUcwMKAG5ldHdvcmtfaWRJ1irQCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:bamboo_button", - "block_state_b64": "CgAAAwgAYmxvY2tfaWT+AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19idXR0b24ECQBuYW1lX2hhc2j7AddMi+6nsgMKAG5ldHdvcmtfaWSa9w4/CgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWT+AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19idXR0b24ECQBuYW1lX2hhc2j7AddMi+6nsgMKAG5ldHdvcmtfaWSa9w4/CgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:stone_button", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRNAAAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX2J1dHRvbgQJAG5hbWVfaGFzaM4ejMctmvohAwoAbmV0d29ya19pZMw+aC0KBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRNAAAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX2J1dHRvbgQJAG5hbWVfaGFzaM4ejMctmvohAwoAbmV0d29ya19pZMw+aC0KBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:crimson_button", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fYnV0dG9uBAkAbmFtZV9oYXNofnjYHaYIeWgDCgBuZXR3b3JrX2lk+n1vyQoGAHN0YXRlcwESAGJ1dHRvbl9wcmVzc2VkX2JpdAADEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fYnV0dG9uBAkAbmFtZV9oYXNofnjYHaYIeWgDCgBuZXR3b3JrX2lk+n1vyQoGAHN0YXRlcwESAGJ1dHRvbl9wcmVzc2VkX2JpdAADEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:warped_button", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQEAgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9idXR0b24ECQBuYW1lX2hhc2jwkV2EU6Cn1QMKAG5ldHdvcmtfaWTnHnk1CgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQEAgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9idXR0b24ECQBuYW1lX2hhc2jwkV2EU6Cn1QMKAG5ldHdvcmtfaWTnHnk1CgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:polished_blackstone_button", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQnAgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnV0dG9uBAkAbmFtZV9oYXNojmxzQKS0S/EDCgBuZXR3b3JrX2lkDtQ95woGAHN0YXRlcwESAGJ1dHRvbl9wcmVzc2VkX2JpdAADEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQnAgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnV0dG9uBAkAbmFtZV9oYXNojmxzQKS0S/EDCgBuZXR3b3JrX2lkDtQ95woGAHN0YXRlcwESAGJ1dHRvbl9wcmVzc2VkX2JpdAADEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:tripwire_hook", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAAAACAQAbmFtZRcAbWluZWNyYWZ0OnRyaXB3aXJlX2hvb2sECQBuYW1lX2hhc2gQdp+oGZLNnAMKAG5ldHdvcmtfaWSy+1KJCgYAc3RhdGVzAQwAYXR0YWNoZWRfYml0AAMJAGRpcmVjdGlvbgAAAAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAAAACAQAbmFtZRcAbWluZWNyYWZ0OnRyaXB3aXJlX2hvb2sECQBuYW1lX2hhc2gQdp+oGZLNnAMKAG5ldHdvcmtfaWSy+1KJCgYAc3RhdGVzAQwAYXR0YWNoZWRfYml0AAMJAGRpcmVjdGlvbgAAAAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:wooden_pressure_plate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRIAAAACAQAbmFtZR8AbWluZWNyYWZ0Ondvb2Rlbl9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaGkGs5kCuA74AwoAbmV0d29ya19pZDRzPNwKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRIAAAACAQAbmFtZR8AbWluZWNyYWZ0Ondvb2Rlbl9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaGkGs5kCuA74AwoAbmV0d29ya19pZDRzPNwKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:spruce_pressure_plate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSZAQAACAQAbmFtZR8AbWluZWNyYWZ0OnNwcnVjZV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaNmwuq549fJKAwoAbmV0d29ya19pZLQMCw0KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSZAQAACAQAbmFtZR8AbWluZWNyYWZ0OnNwcnVjZV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaNmwuq549fJKAwoAbmV0d29ya19pZLQMCw0KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:birch_pressure_plate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSWAQAACAQAbmFtZR4AbWluZWNyYWZ0OmJpcmNoX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNorQkT9kDdlTwDCgBuZXR3b3JrX2lkH0G97AoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSWAQAACAQAbmFtZR4AbWluZWNyYWZ0OmJpcmNoX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNorQkT9kDdlTwDCgBuZXR3b3JrX2lkH0G97AoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:jungle_pressure_plate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSYAQAACAQAbmFtZR8AbWluZWNyYWZ0Omp1bmdsZV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaJ7DcteCkb8/AwoAbmV0d29ya19pZLdPBSAKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSYAQAACAQAbmFtZR8AbWluZWNyYWZ0Omp1bmdsZV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaJ7DcteCkb8/AwoAbmV0d29ya19pZLdPBSAKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:acacia_pressure_plate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSVAQAACAQAbmFtZR8AbWluZWNyYWZ0OmFjYWNpYV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaC2frZtfoYqCAwoAbmV0d29ya19pZIDdI18KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSVAQAACAQAbmFtZR8AbWluZWNyYWZ0OmFjYWNpYV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaC2frZtfoYqCAwoAbmV0d29ya19pZIDdI18KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:dark_oak_pressure_plate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSXAQAACAQAbmFtZSEAbWluZWNyYWZ0OmRhcmtfb2FrX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoHUCJsTy52pwDCgBuZXR3b3JrX2lkKpi8rAoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSXAQAACAQAbmFtZSEAbWluZWNyYWZ0OmRhcmtfb2FrX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoHUCJsTy52pwDCgBuZXR3b3JrX2lkKpi8rAoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:mangrove_pressure_plate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTpAgAACAQAbmFtZSEAbWluZWNyYWZ0Om1hbmdyb3ZlX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoiDsTfJaX100DCgBuZXR3b3JrX2lkuwWDyQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTpAgAACAQAbmFtZSEAbWluZWNyYWZ0Om1hbmdyb3ZlX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoiDsTfJaX100DCgBuZXR3b3JrX2lkuwWDyQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:cherry_pressure_plate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQZAwAACAQAbmFtZR8AbWluZWNyYWZ0OmNoZXJyeV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaALMqYEZDUQHAwoAbmV0d29ya19pZPNT+r0KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQZAwAACAQAbmFtZR8AbWluZWNyYWZ0OmNoZXJyeV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaALMqYEZDUQHAwoAbmV0d29ya19pZPNT+r0KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:bamboo_pressure_plate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAwAACAQAbmFtZR8AbWluZWNyYWZ0OmJhbWJvb19wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaNvxJ7NIAaqlAwoAbmV0d29ya19pZIZ8XnYKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAwAACAQAbmFtZR8AbWluZWNyYWZ0OmJhbWJvb19wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaNvxJ7NIAaqlAwoAbmV0d29ya19pZIZ8XnYKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:crimson_pressure_plate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQFAgAACAQAbmFtZSAAbWluZWNyYWZ0OmNyaW1zb25fcHJlc3N1cmVfcGxhdGUECQBuYW1lX2hhc2hqBDVDAd31/gMKAG5ldHdvcmtfaWRmV18LCgYAc3RhdGVzAw8AcmVkc3RvbmVfc2lnbmFsAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQFAgAACAQAbmFtZSAAbWluZWNyYWZ0OmNyaW1zb25fcHJlc3N1cmVfcGxhdGUECQBuYW1lX2hhc2hqBDVDAd31/gMKAG5ldHdvcmtfaWRmV18LCgYAc3RhdGVzAw8AcmVkc3RvbmVfc2lnbmFsAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:warped_pressure_plate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAgAACAQAbmFtZR8AbWluZWNyYWZ0OndhcnBlZF9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaBxFoQksWtYUAwoAbmV0d29ya19pZJVRoIcKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAgAACAQAbmFtZR8AbWluZWNyYWZ0OndhcnBlZF9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaBxFoQksWtYUAwoAbmV0d29ya19pZJVRoIcKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:stone_pressure_plate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWRGAAAACAQAbmFtZR4AbWluZWNyYWZ0OnN0b25lX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNounJuTBUTrU8DCgBuZXR3b3JrX2lkjDydwQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWRGAAAACAQAbmFtZR4AbWluZWNyYWZ0OnN0b25lX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNounJuTBUTrU8DCgBuZXR3b3JrX2lkjDydwQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:light_weighted_pressure_plate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSTAAAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X3dlaWdodGVkX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoOyOJkNxLtkEDCgBuZXR3b3JrX2lkrr2AjgoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSTAAAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X3dlaWdodGVkX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoOyOJkNxLtkEDCgBuZXR3b3JrX2lkrr2AjgoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:heavy_weighted_pressure_plate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSUAAAACAQAbmFtZScAbWluZWNyYWZ0OmhlYXZ5X3dlaWdodGVkX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoltgDmDvTajUDCgBuZXR3b3JrX2lkFxVKuQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSUAAAACAQAbmFtZScAbWluZWNyYWZ0OmhlYXZ5X3dlaWdodGVkX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoltgDmDvTajUDCgBuZXR3b3JrX2lkFxVKuQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:polished_blackstone_pressure_plate", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAgAACAQAbmFtZSwAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfcHJlc3N1cmVfcGxhdGUECQBuYW1lX2hhc2h65Ci6/CeGqwMKAG5ldHdvcmtfaWTaSW5xCgYAc3RhdGVzAw8AcmVkc3RvbmVfc2lnbmFsAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAgAACAQAbmFtZSwAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfcHJlc3N1cmVfcGxhdGUECQBuYW1lX2hhc2h65Ci6/CeGqwMKAG5ldHdvcmtfaWTaSW5xCgYAc3RhdGVzAw8AcmVkc3RvbmVfc2lnbmFsAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:observer", - "block_state_b64": "CgAAAwgAYmxvY2tfaWT7AAAACAQAbmFtZRIAbWluZWNyYWZ0Om9ic2VydmVyBAkAbmFtZV9oYXNoYhlh1lpmHTgDCgBuZXR3b3JrX2lkQEh55goGAHN0YXRlcwgaAG1pbmVjcmFmdDpmYWNpbmdfZGlyZWN0aW9uBABkb3duAQsAcG93ZXJlZF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWT7AAAACAQAbmFtZRIAbWluZWNyYWZ0Om9ic2VydmVyBAkAbmFtZV9oYXNoYhlh1lpmHTgDCgBuZXR3b3JrX2lkQEh55goGAHN0YXRlcwgaAG1pbmVjcmFmdDpmYWNpbmdfZGlyZWN0aW9uBABkb3duAQsAcG93ZXJlZF9iaXQAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:daylight_detector", - "block_state_b64": "CgAAAwgAYmxvY2tfaWSXAAAACAQAbmFtZRsAbWluZWNyYWZ0OmRheWxpZ2h0X2RldGVjdG9yBAkAbmFtZV9oYXNoV0F0s7B7PVgDCgBuZXR3b3JrX2lkri5afQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWSXAAAACAQAbmFtZRsAbWluZWNyYWZ0OmRheWxpZ2h0X2RldGVjdG9yBAkAbmFtZV9oYXNoV0F0s7B7PVgDCgBuZXR3b3JrX2lkri5afQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:repeater" @@ -5388,30 +5771,34 @@ }, { "id": "minecraft:dropper", - "block_state_b64": "CgAAAwgAYmxvY2tfaWR9AAAACAQAbmFtZREAbWluZWNyYWZ0OmRyb3BwZXIECQBuYW1lX2hhc2joXP7XqU0l3QMKAG5ldHdvcmtfaWQfQN6zCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgMAAAABDQB0cmlnZ2VyZWRfYml0AAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWR9AAAACAQAbmFtZREAbWluZWNyYWZ0OmRyb3BwZXIECQBuYW1lX2hhc2joXP7XqU0l3QMKAG5ldHdvcmtfaWQfQN6zCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgMAAAABDQB0cmlnZ2VyZWRfYml0AAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:dispenser", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQXAAAACAQAbmFtZRMAbWluZWNyYWZ0OmRpc3BlbnNlcgQJAG5hbWVfaGFzaP1RR+zAbYP2AwoAbmV0d29ya19pZGAayD0KBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAwAAAAENAHRyaWdnZXJlZF9iaXQAAAMHAHZlcnNpb24ERhQBAA==" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQXAAAACAQAbmFtZRMAbWluZWNyYWZ0OmRpc3BlbnNlcgQJAG5hbWVfaGFzaP1RR+zAbYP2AwoAbmV0d29ya19pZGAayD0KBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAwAAAAENAHRyaWdnZXJlZF9iaXQAAAMHAHZlcnNpb24DABUBAA==" + }, + { + "id": "minecraft:crafter", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ4AgAACAQAbmFtZREAbWluZWNyYWZ0OmNyYWZ0ZXIECQBuYW1lX2hhc2iLCT/rJmRN8QMKAG5ldHdvcmtfaWTPTbvrCgYAc3RhdGVzAQgAY3JhZnRpbmcACAsAb3JpZW50YXRpb24JAGRvd25fZWFzdAENAHRyaWdnZXJlZF9iaXQAAAMHAHZlcnNpb24DABUBAA==" }, { "id": "minecraft:piston", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQhAAAACAQAbmFtZRAAbWluZWNyYWZ0OnBpc3RvbgQJAG5hbWVfaGFzaDs3AFh1fL0uAwoAbmV0d29ya19pZLD/5XQKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAQAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQhAAAACAQAbmFtZRAAbWluZWNyYWZ0OnBpc3RvbgQJAG5hbWVfaGFzaDs3AFh1fL0uAwoAbmV0d29ya19pZLD/5XQKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAQAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:sticky_piston", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQdAAAACAQAbmFtZRcAbWluZWNyYWZ0OnN0aWNreV9waXN0b24ECQBuYW1lX2hhc2hPFJFJSiJ0ZQMKAG5ldHdvcmtfaWT/MzCJCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgEAAAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQdAAAACAQAbmFtZRcAbWluZWNyYWZ0OnN0aWNreV9waXN0b24ECQBuYW1lX2hhc2hPFJFJSiJ0ZQMKAG5ldHdvcmtfaWT/MzCJCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgEAAAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:tnt", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQuAAAACAQAbmFtZQ0AbWluZWNyYWZ0OnRudAQJAG5hbWVfaGFzaEYOHwCvJH29AwoAbmV0d29ya19pZCGfjU4KBgBzdGF0ZXMBFABhbGxvd191bmRlcndhdGVyX2JpdAABCwBleHBsb2RlX2JpdAAAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQuAAAACAQAbmFtZQ0AbWluZWNyYWZ0OnRudAQJAG5hbWVfaGFzaEYOHwCvJH29AwoAbmV0d29ya19pZCGfjU4KBgBzdGF0ZXMBFABhbGxvd191bmRlcndhdGVyX2JpdAABCwBleHBsb2RlX2JpdAAAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:name_tag" }, { "id": "minecraft:loom", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAQAACAQAbmFtZQ4AbWluZWNyYWZ0Omxvb20ECQBuYW1lX2hhc2i7DKjAXNq8TAMKAG5ldHdvcmtfaWR/49HXCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAQAACAQAbmFtZQ4AbWluZWNyYWZ0Omxvb20ECQBuYW1lX2hhc2i7DKjAXNq8TAMKAG5ldHdvcmtfaWR/49HXCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:banner", @@ -5521,6 +5908,12 @@ { "id": "minecraft:globe_banner_pattern" }, + { + "id": "minecraft:flow_banner_pattern" + }, + { + "id": "minecraft:guster_banner_pattern" + }, { "id": "minecraft:angler_pottery_sherd" }, @@ -5545,9 +5938,15 @@ { "id": "minecraft:explorer_pottery_sherd" }, + { + "id": "minecraft:flow_pottery_sherd" + }, { "id": "minecraft:friend_pottery_sherd" }, + { + "id": "minecraft:guster_pottery_sherd" + }, { "id": "minecraft:heart_pottery_sherd" }, @@ -5569,6 +5968,9 @@ { "id": "minecraft:prize_pottery_sherd" }, + { + "id": "minecraft:scrape_pottery_sherd" + }, { "id": "minecraft:sheaf_pottery_sherd" }, @@ -5632,6 +6034,12 @@ { "id": "minecraft:spire_armor_trim_smithing_template" }, + { + "id": "minecraft:flow_armor_trim_smithing_template" + }, + { + "id": "minecraft:bolt_armor_trim_smithing_template" + }, { "id": "minecraft:firework_rocket", "nbt_b64": "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwAAAAAAAQYARmxpZ2h0AQAA" @@ -5784,11 +6192,11 @@ }, { "id": "minecraft:target", - "block_state_b64": "CgAAAwgAYmxvY2tfaWTuAQAACAQAbmFtZRAAbWluZWNyYWZ0OnRhcmdldAQJAG5hbWVfaGFzaJc66SVbYlaxAwoAbmV0d29ya19pZPBozs0KBgBzdGF0ZXMAAwcAdmVyc2lvbgRGFAEA" + "block_state_b64": "CgAAAwgAYmxvY2tfaWTuAQAACAQAbmFtZRAAbWluZWNyYWZ0OnRhcmdldAQJAG5hbWVfaGFzaJc66SVbYlaxAwoAbmV0d29ya19pZPBozs0KBgBzdGF0ZXMAAwcAdmVyc2lvbgMAFQEA" }, { "id": "minecraft:decorated_pot", - "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAwAACAQAbmFtZRcAbWluZWNyYWZ0OmRlY29yYXRlZF9wb3QECQBuYW1lX2hhc2jjQgckn8VTvwMKAG5ldHdvcmtfaWRwvkUUCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBEYUAQA=" + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAwAACAQAbmFtZRcAbWluZWNyYWZ0OmRlY29yYXRlZF9wb3QECQBuYW1lX2hhc2jjQgckn8VTvwMKAG5ldHdvcmtfaWRwvkUUCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uAwAVAQA=" }, { "id": "minecraft:lodestone_compass" @@ -5798,6 +6206,9 @@ }, { "id": "minecraft:ender_dragon_spawn_egg" + }, + { + "id": "minecraft:ominous_trial_key" } ] } \ 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 9a123f8d8834e6af5c98b000778665b6e2022887..e7cdeb08e65d446bef173af7cea4bc56d5023df3 100644 GIT binary patch delta 204 zcmeCT`{lsP#lXpynUa%PT*B4BG})0+V)7Yo?u`b#lKSeonR%(nMTu!8R!K#vsa2`* z<(YXY@yQv9Md_*W1x5K;smUdoIjPLdMVTqHm?j$ts7?zsAI&p#=FT`rF%nYW<3waEAlk(HkQ&Yeq N3qT^mlTXXJ006xXMWO%z delta 39 vcmez6&~L}f#lXpynUa%PT*CE@ak3+$#N;#F+#3yeB{%Cx^|4MiQ*Z$Q^=b>+ 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 deleted file mode 100644 index 861b29c8a..000000000 --- a/core/src/main/resources/bedrock/runtime_item_states.1_20_40.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 diff --git a/core/src/main/resources/bedrock/runtime_item_states.1_20_50.json b/core/src/main/resources/bedrock/runtime_item_states.1_20_50.json deleted file mode 100644 index d7535269f..000000000 --- a/core/src/main/resources/bedrock/runtime_item_states.1_20_50.json +++ /dev/null @@ -1,5846 +0,0 @@ -[ - { - "name": "minecraft:acacia_boat", - "id": 382 - }, - { - "name": "minecraft:acacia_button", - "id": -140 - }, - { - "name": "minecraft:acacia_chest_boat", - "id": 650 - }, - { - "name": "minecraft:acacia_door", - "id": 564 - }, - { - "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": 587 - }, - { - "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": 639 - }, - { - "name": "minecraft:allow", - "id": 210 - }, - { - "name": "minecraft:amethyst_block", - "id": -327 - }, - { - "name": "minecraft:amethyst_cluster", - "id": -329 - }, - { - "name": "minecraft:amethyst_shard", - "id": 632 - }, - { - "name": "minecraft:ancient_debris", - "id": -271 - }, - { - "name": "minecraft:andesite", - "id": -594 - }, - { - "name": "minecraft:andesite_stairs", - "id": -171 - }, - { - "name": "minecraft:angler_pottery_sherd", - "id": 664 - }, - { - "name": "minecraft:anvil", - "id": 145 - }, - { - "name": "minecraft:apple", - "id": 257 - }, - { - "name": "minecraft:archer_pottery_sherd", - "id": 665 - }, - { - "name": "minecraft:armor_stand", - "id": 560 - }, - { - "name": "minecraft:arms_up_pottery_sherd", - "id": 666 - }, - { - "name": "minecraft:arrow", - "id": 304 - }, - { - "name": "minecraft:axolotl_bucket", - "id": 372 - }, - { - "name": "minecraft:axolotl_spawn_egg", - "id": 504 - }, - { - "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": 606 - }, - { - "name": "minecraft:bamboo", - "id": -163 - }, - { - "name": "minecraft:bamboo_block", - "id": -527 - }, - { - "name": "minecraft:bamboo_button", - "id": -511 - }, - { - "name": "minecraft:bamboo_chest_raft", - "id": 662 - }, - { - "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": 661 - }, - { - "name": "minecraft:bamboo_sapling", - "id": -164 - }, - { - "name": "minecraft:bamboo_sign", - "id": 660 - }, - { - "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": 575 - }, - { - "name": "minecraft:banner_pattern", - "id": 718 - }, - { - "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": 647 - }, - { - "name": "minecraft:birch_door", - "id": 562 - }, - { - "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": 585 - }, - { - "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": 667 - }, - { - "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": 604 - }, - { - "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": 716 - }, - { - "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": 594 - }, - { - "name": "minecraft:bow", - "id": 303 - }, - { - "name": "minecraft:bowl", - "id": 324 - }, - { - "name": "minecraft:brain_coral", - "id": -581 - }, - { - "name": "minecraft:bread", - "id": 262 - }, - { - "name": "minecraft:brewer_pottery_sherd", - "id": 668 - }, - { - "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": 684 - }, - { - "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": 669 - }, - { - "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": 663 - }, - { - "name": "minecraft:camera", - "id": 601 - }, - { - "name": "minecraft:campfire", - "id": 597 - }, - { - "name": "minecraft:candle", - "id": -412 - }, - { - "name": "minecraft:candle_cake", - "id": -429 - }, - { - "name": "minecraft:carpet", - "id": 705 - }, - { - "name": "minecraft:carrot", - "id": 280 - }, - { - "name": "minecraft:carrot_on_a_stick", - "id": 525 - }, - { - "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": 627 - }, - { - "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": 657 - }, - { - "name": "minecraft:cherry_button", - "id": -530 - }, - { - "name": "minecraft:cherry_chest_boat", - "id": 658 - }, - { - "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": 659 - }, - { - "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": 653 - }, - { - "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": 566 - }, - { - "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": 688 - }, - { - "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": 571 - }, - { - "name": "minecraft:comparator", - "id": 530 - }, - { - "name": "minecraft:compass", - "id": 394 - }, - { - "name": "minecraft:composter", - "id": -213 - }, - { - "name": "minecraft:compound", - "id": 602 - }, - { - "name": "minecraft:concrete", - "id": 711 - }, - { - "name": "minecraft:concrete_powder", - "id": 712 - }, - { - "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": 559 - }, - { - "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": 512 - }, - { - "name": "minecraft:copper_ore", - "id": -311 - }, - { - "name": "minecraft:copper_trapdoor", - "id": -792 - }, - { - "name": "minecraft:coral", - "id": 709 - }, - { - "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": 590 - }, - { - "name": "minecraft:creeper_spawn_egg", - "id": 444 - }, - { - "name": "minecraft:crimson_button", - "id": -260 - }, - { - "name": "minecraft:crimson_door", - "id": 624 - }, - { - "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": 622 - }, - { - "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": 583 - }, - { - "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": 670 - }, - { - "name": "minecraft:dark_oak_boat", - "id": 383 - }, - { - "name": "minecraft:dark_oak_button", - "id": -142 - }, - { - "name": "minecraft:dark_oak_chest_boat", - "id": 651 - }, - { - "name": "minecraft:dark_oak_door", - "id": 565 - }, - { - "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": 588 - }, - { - "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": 541 - }, - { - "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": 645 - }, - { - "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": 568 - }, - { - "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": 687 - }, - { - "name": "minecraft:dye", - "id": 717 - }, - { - "name": "minecraft:echo_shard", - "id": 655 - }, - { - "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": 572 - }, - { - "name": "minecraft:emerald", - "id": 520 - }, - { - "name": "minecraft:emerald_block", - "id": 133 - }, - { - "name": "minecraft:emerald_ore", - "id": 129 - }, - { - "name": "minecraft:empty_map", - "id": 523 - }, - { - "name": "minecraft:enchanted_book", - "id": 529 - }, - { - "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": 720 - }, - { - "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": 509 - }, - { - "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": 516 - }, - { - "name": "minecraft:explorer_pottery_sherd", - "id": 671 - }, - { - "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": 691 - }, - { - "name": "minecraft:farmland", - "id": 60 - }, - { - "name": "minecraft:feather", - "id": 330 - }, - { - "name": "minecraft:fence", - "id": 707 - }, - { - "name": "minecraft:fence_gate", - "id": 107 - }, - { - "name": "minecraft:fermented_spider_eye", - "id": 431 - }, - { - "name": "minecraft:field_masoned_banner_pattern", - "id": 593 - }, - { - "name": "minecraft:filled_map", - "id": 423 - }, - { - "name": "minecraft:fire", - "id": 51 - }, - { - "name": "minecraft:fire_charge", - "id": 517 - }, - { - "name": "minecraft:fire_coral", - "id": -583 - }, - { - "name": "minecraft:firework_rocket", - "id": 527 - }, - { - "name": "minecraft:firework_star", - "id": 528 - }, - { - "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": 589 - }, - { - "name": "minecraft:flower_pot", - "id": 522 - }, - { - "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": 521 - }, - { - "name": "minecraft:friend_pottery_sherd", - "id": 672 - }, - { - "name": "minecraft:frog_spawn", - "id": -468 - }, - { - "name": "minecraft:frog_spawn_egg", - "id": 636 - }, - { - "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": 596 - }, - { - "name": "minecraft:glow_berries", - "id": 721 - }, - { - "name": "minecraft:glow_frame", - "id": 631 - }, - { - "name": "minecraft:glow_ink_sac", - "id": 511 - }, - { - "name": "minecraft:glow_lichen", - "id": -411 - }, - { - "name": "minecraft:glow_squid_spawn_egg", - "id": 506 - }, - { - "name": "minecraft:glow_stick", - "id": 609 - }, - { - "name": "minecraft:glowingobsidian", - "id": 246 - }, - { - "name": "minecraft:glowstone", - "id": 89 - }, - { - "name": "minecraft:glowstone_dust", - "id": 397 - }, - { - "name": "minecraft:goat_horn", - "id": 635 - }, - { - "name": "minecraft:goat_spawn_egg", - "id": 505 - }, - { - "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": 540 - }, - { - "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_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": 579 - }, - { - "name": "minecraft:heart_pottery_sherd", - "id": 673 - }, - { - "name": "minecraft:heartbreak_pottery_sherd", - "id": 674 - }, - { - "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": 600 - }, - { - "name": "minecraft:honeycomb", - "id": 599 - }, - { - "name": "minecraft:honeycomb_block", - "id": -221 - }, - { - "name": "minecraft:hopper", - "id": 535 - }, - { - "name": "minecraft:hopper_minecart", - "id": 534 - }, - { - "name": "minecraft:horn_coral", - "id": -584 - }, - { - "name": "minecraft:horse_spawn_egg", - "id": 461 - }, - { - "name": "minecraft:host_armor_trim_smithing_template", - "id": 701 - }, - { - "name": "minecraft:howl_pottery_sherd", - "id": 675 - }, - { - "name": "minecraft:husk_spawn_egg", - "id": 466 - }, - { - "name": "minecraft:ice", - "id": 79 - }, - { - "name": "minecraft:ice_bomb", - "id": 603 - }, - { - "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": 507 - }, - { - "name": "minecraft:iron_helmet", - "id": 346 - }, - { - "name": "minecraft:iron_hoe", - "id": 334 - }, - { - "name": "minecraft:iron_horse_armor", - "id": 539 - }, - { - "name": "minecraft:iron_ingot", - "id": 308 - }, - { - "name": "minecraft:iron_leggings", - "id": 348 - }, - { - "name": "minecraft:iron_nugget", - "id": 577 - }, - { - "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": 648 - }, - { - "name": "minecraft:jungle_door", - "id": 563 - }, - { - "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": 586 - }, - { - "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": 555 - }, - { - "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": 538 - }, - { - "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": 570 - }, - { - "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": 610 - }, - { - "name": "minecraft:log", - "id": 706 - }, - { - "name": "minecraft:log2", - "id": 710 - }, - { - "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": 643 - }, - { - "name": "minecraft:mangrove_button", - "id": -487 - }, - { - "name": "minecraft:mangrove_chest_boat", - "id": 652 - }, - { - "name": "minecraft:mangrove_door", - "id": 641 - }, - { - "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": 642 - }, - { - "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": 607 - }, - { - "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": 676 - }, - { - "name": "minecraft:mob_spawner", - "id": 52 - }, - { - "name": "minecraft:mojang_banner_pattern", - "id": 592 - }, - { - "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": 677 - }, - { - "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": 552 - }, - { - "name": "minecraft:music_disc_13", - "id": 542 - }, - { - "name": "minecraft:music_disc_5", - "id": 644 - }, - { - "name": "minecraft:music_disc_blocks", - "id": 544 - }, - { - "name": "minecraft:music_disc_cat", - "id": 543 - }, - { - "name": "minecraft:music_disc_chirp", - "id": 545 - }, - { - "name": "minecraft:music_disc_far", - "id": 546 - }, - { - "name": "minecraft:music_disc_mall", - "id": 547 - }, - { - "name": "minecraft:music_disc_mellohi", - "id": 548 - }, - { - "name": "minecraft:music_disc_otherside", - "id": 634 - }, - { - "name": "minecraft:music_disc_pigstep", - "id": 628 - }, - { - "name": "minecraft:music_disc_relic", - "id": 702 - }, - { - "name": "minecraft:music_disc_stal", - "id": 549 - }, - { - "name": "minecraft:music_disc_strad", - "id": 550 - }, - { - "name": "minecraft:music_disc_wait", - "id": 553 - }, - { - "name": "minecraft:music_disc_ward", - "id": 551 - }, - { - "name": "minecraft:mutton", - "id": 558 - }, - { - "name": "minecraft:mycelium", - "id": 110 - }, - { - "name": "minecraft:name_tag", - "id": 556 - }, - { - "name": "minecraft:nautilus_shell", - "id": 578 - }, - { - "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": 629 - }, - { - "name": "minecraft:nether_star", - "id": 526 - }, - { - "name": "minecraft:nether_wart", - "id": 295 - }, - { - "name": "minecraft:nether_wart_block", - "id": 214 - }, - { - "name": "minecraft:netherbrick", - "id": 531 - }, - { - "name": "minecraft:netherite_axe", - "id": 614 - }, - { - "name": "minecraft:netherite_block", - "id": -270 - }, - { - "name": "minecraft:netherite_boots", - "id": 620 - }, - { - "name": "minecraft:netherite_chestplate", - "id": 618 - }, - { - "name": "minecraft:netherite_helmet", - "id": 617 - }, - { - "name": "minecraft:netherite_hoe", - "id": 615 - }, - { - "name": "minecraft:netherite_ingot", - "id": 616 - }, - { - "name": "minecraft:netherite_leggings", - "id": 619 - }, - { - "name": "minecraft:netherite_pickaxe", - "id": 613 - }, - { - "name": "minecraft:netherite_scrap", - "id": 621 - }, - { - "name": "minecraft:netherite_shovel", - "id": 612 - }, - { - "name": "minecraft:netherite_sword", - "id": 611 - }, - { - "name": "minecraft:netherite_upgrade_smithing_template", - "id": 685 - }, - { - "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": 646 - }, - { - "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": 582 - }, - { - "name": "minecraft:phantom_spawn_egg", - "id": 489 - }, - { - "name": "minecraft:pig_spawn_egg", - "id": 440 - }, - { - "name": "minecraft:piglin_banner_pattern", - "id": 595 - }, - { - "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": 708 - }, - { - "name": "minecraft:plenty_pottery_sherd", - "id": 678 - }, - { - "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": 567 - }, - { - "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": 557 - }, - { - "name": "minecraft:prismarine_shard", - "id": 573 - }, - { - "name": "minecraft:prismarine_stairs", - "id": -2 - }, - { - "name": "minecraft:prize_pottery_sherd", - "id": 679 - }, - { - "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": 532 - }, - { - "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": 536 - }, - { - "name": "minecraft:rabbit_hide", - "id": 537 - }, - { - "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": 699 - }, - { - "name": "minecraft:rapid_fertilizer", - "id": 605 - }, - { - "name": "minecraft:ravager_spawn_egg", - "id": 496 - }, - { - "name": "minecraft:raw_copper", - "id": 515 - }, - { - "name": "minecraft:raw_copper_block", - "id": -452 - }, - { - "name": "minecraft:raw_gold", - "id": 514 - }, - { - "name": "minecraft:raw_gold_block", - "id": -453 - }, - { - "name": "minecraft:raw_iron", - "id": 513 - }, - { - "name": "minecraft:raw_iron_block", - "id": -451 - }, - { - "name": "minecraft:recovery_compass", - "id": 654 - }, - { - "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": 695 - }, - { - "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:scute", - "id": 580 - }, - { - "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": 686 - }, - { - "name": "minecraft:shaper_armor_trim_smithing_template", - "id": 700 - }, - { - "name": "minecraft:sheaf_pottery_sherd", - "id": 680 - }, - { - "name": "minecraft:shears", - "id": 424 - }, - { - "name": "minecraft:sheep_spawn_egg", - "id": 441 - }, - { - "name": "minecraft:shelter_pottery_sherd", - "id": 681 - }, - { - "name": "minecraft:shield", - "id": 358 - }, - { - "name": "minecraft:shroomlight", - "id": -230 - }, - { - "name": "minecraft:shulker_box", - "id": 715 - }, - { - "name": "minecraft:shulker_shell", - "id": 574 - }, - { - "name": "minecraft:shulker_spawn_egg", - "id": 472 - }, - { - "name": "minecraft:silence_armor_trim_smithing_template", - "id": 697 - }, - { - "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": 524 - }, - { - "name": "minecraft:skull_banner_pattern", - "id": 591 - }, - { - "name": "minecraft:skull_pottery_sherd", - "id": 682 - }, - { - "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": 683 - }, - { - "name": "minecraft:snout_armor_trim_smithing_template", - "id": 694 - }, - { - "name": "minecraft:snow", - "id": 80 - }, - { - "name": "minecraft:snow_golem_spawn_egg", - "id": 508 - }, - { - "name": "minecraft:snow_layer", - "id": 78 - }, - { - "name": "minecraft:snowball", - "id": 377 - }, - { - "name": "minecraft:soul_campfire", - "id": 630 - }, - { - "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": 608 - }, - { - "name": "minecraft:spawn_egg", - "id": 719 - }, - { - "name": "minecraft:spider_eye", - "id": 279 - }, - { - "name": "minecraft:spider_spawn_egg", - "id": 449 - }, - { - "name": "minecraft:spire_armor_trim_smithing_template", - "id": 696 - }, - { - "name": "minecraft:splash_potion", - "id": 569 - }, - { - "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": 649 - }, - { - "name": "minecraft:spruce_door", - "id": 561 - }, - { - "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": 584 - }, - { - "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": 633 - }, - { - "name": "minecraft:squid_spawn_egg", - "id": 453 - }, - { - "name": "minecraft:stained_glass", - "id": 713 - }, - { - "name": "minecraft:stained_glass_pane", - "id": 714 - }, - { - "name": "minecraft:stained_hardened_clay", - "id": 703 - }, - { - "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": 598 - }, - { - "name": "minecraft:sweet_berries", - "id": 288 - }, - { - "name": "minecraft:sweet_berry_bush", - "id": -207 - }, - { - "name": "minecraft:tadpole_bucket", - "id": 638 - }, - { - "name": "minecraft:tadpole_spawn_egg", - "id": 637 - }, - { - "name": "minecraft:tallgrass", - "id": 31 - }, - { - "name": "minecraft:target", - "id": -239 - }, - { - "name": "minecraft:tide_armor_trim_smithing_template", - "id": 693 - }, - { - "name": "minecraft:tinted_glass", - "id": -334 - }, - { - "name": "minecraft:tnt", - "id": 46 - }, - { - "name": "minecraft:tnt_minecart", - "id": 533 - }, - { - "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": 576 - }, - { - "name": "minecraft:trader_llama_spawn_egg", - "id": 656 - }, - { - "name": "minecraft:trapdoor", - "id": 96 - }, - { - "name": "minecraft:trapped_chest", - "id": 146 - }, - { - "name": "minecraft:trident", - "id": 554 - }, - { - "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": 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": 692 - }, - { - "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": 690 - }, - { - "name": "minecraft:warden_spawn_egg", - "id": 640 - }, - { - "name": "minecraft:warped_button", - "id": -261 - }, - { - "name": "minecraft:warped_door", - "id": 625 - }, - { - "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": 626 - }, - { - "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": 623 - }, - { - "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": 698 - }, - { - "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": 689 - }, - { - "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": 510 - }, - { - "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": 704 - }, - { - "name": "minecraft:writable_book", - "id": 518 - }, - { - "name": "minecraft:written_book", - "id": 519 - }, - { - "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/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 deleted file mode 100644 index f8b3199e3..000000000 --- a/core/src/main/resources/bedrock/runtime_item_states.1_20_60.json +++ /dev/null @@ -1,5998 +0,0 @@ -[ - { - "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/core/src/main/resources/bedrock/runtime_item_states.1_20_70.json b/core/src/main/resources/bedrock/runtime_item_states.1_21_0.json similarity index 95% rename from core/src/main/resources/bedrock/runtime_item_states.1_20_70.json rename to core/src/main/resources/bedrock/runtime_item_states.1_21_0.json index 887b89ba1..1430a5437 100644 --- a/core/src/main/resources/bedrock/runtime_item_states.1_20_70.json +++ b/core/src/main/resources/bedrock/runtime_item_states.1_21_0.json @@ -1,7 +1,7 @@ [ { "name": "minecraft:acacia_boat", - "id": 383 + "id": 387 }, { "name": "minecraft:acacia_button", @@ -9,11 +9,11 @@ }, { "name": "minecraft:acacia_chest_boat", - "id": 653 + "id": 661 }, { "name": "minecraft:acacia_door", - "id": 567 + "id": 572 }, { "name": "minecraft:acacia_double_slab", @@ -47,9 +47,13 @@ "name": "minecraft:acacia_pressure_plate", "id": -150 }, + { + "name": "minecraft:acacia_sapling", + "id": -828 + }, { "name": "minecraft:acacia_sign", - "id": 590 + "id": 595 }, { "name": "minecraft:acacia_slab", @@ -81,7 +85,7 @@ }, { "name": "minecraft:agent_spawn_egg", - "id": 492 + "id": 497 }, { "name": "minecraft:air", @@ -89,7 +93,11 @@ }, { "name": "minecraft:allay_spawn_egg", - "id": 642 + "id": 650 + }, + { + "name": "minecraft:allium", + "id": -831 }, { "name": "minecraft:allow", @@ -105,7 +113,7 @@ }, { "name": "minecraft:amethyst_shard", - "id": 635 + "id": 643 }, { "name": "minecraft:ancient_debris", @@ -121,7 +129,7 @@ }, { "name": "minecraft:angler_pottery_sherd", - "id": 667 + "id": 675 }, { "name": "minecraft:anvil", @@ -133,35 +141,35 @@ }, { "name": "minecraft:archer_pottery_sherd", - "id": 668 + "id": 676 }, { "name": "minecraft:armadillo_scute", - "id": 709 + "id": 721 }, { "name": "minecraft:armadillo_spawn_egg", - "id": 708 + "id": 720 }, { "name": "minecraft:armor_stand", - "id": 563 + "id": 568 }, { "name": "minecraft:arms_up_pottery_sherd", - "id": 669 + "id": 677 }, { "name": "minecraft:arrow", - "id": 304 + "id": 307 }, { "name": "minecraft:axolotl_bucket", - "id": 372 + "id": 376 }, { "name": "minecraft:axolotl_spawn_egg", - "id": 507 + "id": 512 }, { "name": "minecraft:azalea", @@ -175,13 +183,17 @@ "name": "minecraft:azalea_leaves_flowered", "id": -325 }, + { + "name": "minecraft:azure_bluet", + "id": -832 + }, { "name": "minecraft:baked_potato", - "id": 282 + "id": 285 }, { "name": "minecraft:balloon", - "id": 609 + "id": 617 }, { "name": "minecraft:bamboo", @@ -197,7 +209,7 @@ }, { "name": "minecraft:bamboo_chest_raft", - "id": 665 + "id": 673 }, { "name": "minecraft:bamboo_door", @@ -245,7 +257,7 @@ }, { "name": "minecraft:bamboo_raft", - "id": 664 + "id": 672 }, { "name": "minecraft:bamboo_sapling", @@ -253,7 +265,7 @@ }, { "name": "minecraft:bamboo_sign", - "id": 663 + "id": 671 }, { "name": "minecraft:bamboo_slab", @@ -277,11 +289,11 @@ }, { "name": "minecraft:banner", - "id": 578 + "id": 583 }, { "name": "minecraft:banner_pattern", - "id": 731 + "id": 756 }, { "name": "minecraft:barrel", @@ -297,7 +309,7 @@ }, { "name": "minecraft:bat_spawn_egg", - "id": 457 + "id": 462 }, { "name": "minecraft:beacon", @@ -305,7 +317,7 @@ }, { "name": "minecraft:bed", - "id": 422 + "id": 426 }, { "name": "minecraft:bedrock", @@ -317,11 +329,11 @@ }, { "name": "minecraft:bee_spawn_egg", - "id": 499 + "id": 504 }, { "name": "minecraft:beef", - "id": 274 + "id": 277 }, { "name": "minecraft:beehive", @@ -329,15 +341,15 @@ }, { "name": "minecraft:beetroot", - "id": 286 + "id": 289 }, { "name": "minecraft:beetroot_seeds", - "id": 296 + "id": 299 }, { "name": "minecraft:beetroot_soup", - "id": 287 + "id": 290 }, { "name": "minecraft:bell", @@ -349,7 +361,7 @@ }, { "name": "minecraft:birch_boat", - "id": 380 + "id": 384 }, { "name": "minecraft:birch_button", @@ -357,11 +369,11 @@ }, { "name": "minecraft:birch_chest_boat", - "id": 650 + "id": 658 }, { "name": "minecraft:birch_door", - "id": 565 + "id": 570 }, { "name": "minecraft:birch_double_slab", @@ -395,9 +407,13 @@ "name": "minecraft:birch_pressure_plate", "id": -151 }, + { + "name": "minecraft:birch_sapling", + "id": -826 + }, { "name": "minecraft:birch_sign", - "id": 588 + "id": 593 }, { "name": "minecraft:birch_slab", @@ -445,7 +461,7 @@ }, { "name": "minecraft:black_dye", - "id": 399 + "id": 403 }, { "name": "minecraft:black_glazed_terracotta", @@ -493,7 +509,7 @@ }, { "name": "minecraft:blade_pottery_sherd", - "id": 670 + "id": 678 }, { "name": "minecraft:blast_furnace", @@ -501,19 +517,19 @@ }, { "name": "minecraft:blaze_powder", - "id": 433 + "id": 438 }, { "name": "minecraft:blaze_rod", - "id": 427 + "id": 431 }, { "name": "minecraft:blaze_spawn_egg", - "id": 460 + "id": 465 }, { "name": "minecraft:bleach", - "id": 607 + "id": 615 }, { "name": "minecraft:blue_candle", @@ -537,7 +553,7 @@ }, { "name": "minecraft:blue_dye", - "id": 403 + "id": 407 }, { "name": "minecraft:blue_glazed_terracotta", @@ -547,6 +563,10 @@ "name": "minecraft:blue_ice", "id": -11 }, + { + "name": "minecraft:blue_orchid", + "id": -830 + }, { "name": "minecraft:blue_shulker_box", "id": -623 @@ -569,15 +589,19 @@ }, { "name": "minecraft:boat", - "id": 729 + "id": 754 }, { "name": "minecraft:bogged_spawn_egg", - "id": 467 + "id": 472 + }, + { + "name": "minecraft:bolt_armor_trim_smithing_template", + "id": 717 }, { "name": "minecraft:bone", - "id": 419 + "id": 423 }, { "name": "minecraft:bone_block", @@ -585,11 +609,11 @@ }, { "name": "minecraft:bone_meal", - "id": 415 + "id": 419 }, { "name": "minecraft:book", - "id": 391 + "id": 395 }, { "name": "minecraft:bookshelf", @@ -601,44 +625,60 @@ }, { "name": "minecraft:bordure_indented_banner_pattern", - "id": 597 + "id": 602 }, { "name": "minecraft:bow", - "id": 303 + "id": 306 }, { "name": "minecraft:bowl", - "id": 324 + "id": 328 }, { "name": "minecraft:brain_coral", "id": -581 }, + { + "name": "minecraft:brain_coral_block", + "id": -849 + }, + { + "name": "minecraft:brain_coral_fan", + "id": -840 + }, { "name": "minecraft:bread", - "id": 262 + "id": 265 + }, + { + "name": "minecraft:breeze_rod", + "id": 432 }, { "name": "minecraft:breeze_spawn_egg", - "id": 506 + "id": 511 }, { "name": "minecraft:brewer_pottery_sherd", - "id": 671 + "id": 679 }, { "name": "minecraft:brewing_stand", - "id": 435 + "id": 440 }, { "name": "minecraft:brick", - "id": 387 + "id": 391 }, { "name": "minecraft:brick_block", "id": 45 }, + { + "name": "minecraft:brick_slab", + "id": -874 + }, { "name": "minecraft:brick_stairs", "id": 108 @@ -665,7 +705,7 @@ }, { "name": "minecraft:brown_dye", - "id": 402 + "id": 406 }, { "name": "minecraft:brown_glazed_terracotta", @@ -701,7 +741,7 @@ }, { "name": "minecraft:brush", - "id": 687 + "id": 698 }, { "name": "minecraft:bubble_column", @@ -711,9 +751,17 @@ "name": "minecraft:bubble_coral", "id": -582 }, + { + "name": "minecraft:bubble_coral_block", + "id": -850 + }, + { + "name": "minecraft:bubble_coral_fan", + "id": -841 + }, { "name": "minecraft:bucket", - "id": 363 + "id": 367 }, { "name": "minecraft:budding_amethyst", @@ -721,7 +769,7 @@ }, { "name": "minecraft:burn_pottery_sherd", - "id": 672 + "id": 680 }, { "name": "minecraft:cactus", @@ -729,7 +777,7 @@ }, { "name": "minecraft:cake", - "id": 421 + "id": 425 }, { "name": "minecraft:calcite", @@ -741,15 +789,15 @@ }, { "name": "minecraft:camel_spawn_egg", - "id": 666 + "id": 674 }, { "name": "minecraft:camera", - "id": 604 + "id": 612 }, { "name": "minecraft:campfire", - "id": 600 + "id": 607 }, { "name": "minecraft:candle", @@ -761,15 +809,15 @@ }, { "name": "minecraft:carpet", - "id": 712 + "id": 726 }, { "name": "minecraft:carrot", - "id": 280 + "id": 283 }, { "name": "minecraft:carrot_on_a_stick", - "id": 528 + "id": 533 }, { "name": "minecraft:carrots", @@ -785,15 +833,15 @@ }, { "name": "minecraft:cat_spawn_egg", - "id": 493 + "id": 498 }, { "name": "minecraft:cauldron", - "id": 436 + "id": 441 }, { "name": "minecraft:cave_spider_spawn_egg", - "id": 461 + "id": 466 }, { "name": "minecraft:cave_vines", @@ -809,7 +857,7 @@ }, { "name": "minecraft:chain", - "id": 630 + "id": 638 }, { "name": "minecraft:chain_command_block", @@ -817,23 +865,23 @@ }, { "name": "minecraft:chainmail_boots", - "id": 345 + "id": 349 }, { "name": "minecraft:chainmail_chestplate", - "id": 343 + "id": 347 }, { "name": "minecraft:chainmail_helmet", - "id": 342 + "id": 346 }, { "name": "minecraft:chainmail_leggings", - "id": 344 + "id": 348 }, { "name": "minecraft:charcoal", - "id": 306 + "id": 309 }, { "name": "minecraft:chemical_heat", @@ -845,7 +893,7 @@ }, { "name": "minecraft:cherry_boat", - "id": 660 + "id": 668 }, { "name": "minecraft:cherry_button", @@ -853,7 +901,7 @@ }, { "name": "minecraft:cherry_chest_boat", - "id": 661 + "id": 669 }, { "name": "minecraft:cherry_door", @@ -897,7 +945,7 @@ }, { "name": "minecraft:cherry_sign", - "id": 662 + "id": 670 }, { "name": "minecraft:cherry_slab", @@ -929,19 +977,19 @@ }, { "name": "minecraft:chest_boat", - "id": 656 + "id": 664 }, { "name": "minecraft:chest_minecart", - "id": 393 + "id": 397 }, { "name": "minecraft:chicken", - "id": 276 + "id": 279 }, { "name": "minecraft:chicken_spawn_egg", - "id": 439 + "id": 444 }, { "name": "minecraft:chiseled_bookshelf", @@ -977,7 +1025,7 @@ }, { "name": "minecraft:chorus_fruit", - "id": 569 + "id": 574 }, { "name": "minecraft:chorus_plant", @@ -989,7 +1037,7 @@ }, { "name": "minecraft:clay_ball", - "id": 388 + "id": 392 }, { "name": "minecraft:client_request_placeholder_block", @@ -997,11 +1045,11 @@ }, { "name": "minecraft:clock", - "id": 397 + "id": 401 }, { "name": "minecraft:coal", - "id": 305 + "id": 308 }, { "name": "minecraft:coal_block", @@ -1013,7 +1061,7 @@ }, { "name": "minecraft:coast_armor_trim_smithing_template", - "id": 691 + "id": 702 }, { "name": "minecraft:cobbled_deepslate", @@ -1039,6 +1087,10 @@ "name": "minecraft:cobblestone", "id": 4 }, + { + "name": "minecraft:cobblestone_slab", + "id": -873 + }, { "name": "minecraft:cobblestone_wall", "id": 139 @@ -1049,19 +1101,19 @@ }, { "name": "minecraft:cocoa_beans", - "id": 416 + "id": 420 }, { "name": "minecraft:cod", - "id": 265 + "id": 268 }, { "name": "minecraft:cod_bucket", - "id": 367 + "id": 371 }, { "name": "minecraft:cod_spawn_egg", - "id": 485 + "id": 490 }, { "name": "minecraft:colored_torch_bp", @@ -1077,15 +1129,15 @@ }, { "name": "minecraft:command_block_minecart", - "id": 574 + "id": 579 }, { "name": "minecraft:comparator", - "id": 533 + "id": 538 }, { "name": "minecraft:compass", - "id": 395 + "id": 399 }, { "name": "minecraft:composter", @@ -1093,15 +1145,15 @@ }, { "name": "minecraft:compound", - "id": 605 + "id": 613 }, { "name": "minecraft:concrete", - "id": 721 + "id": 743 }, { "name": "minecraft:concrete_powder", - "id": 722 + "id": 744 }, { "name": "minecraft:conduit", @@ -1109,35 +1161,35 @@ }, { "name": "minecraft:cooked_beef", - "id": 275 + "id": 278 }, { "name": "minecraft:cooked_chicken", - "id": 277 + "id": 280 }, { "name": "minecraft:cooked_cod", - "id": 269 + "id": 272 }, { "name": "minecraft:cooked_mutton", - "id": 562 + "id": 567 }, { "name": "minecraft:cooked_porkchop", - "id": 264 + "id": 267 }, { "name": "minecraft:cooked_rabbit", - "id": 290 + "id": 293 }, { "name": "minecraft:cooked_salmon", - "id": 270 + "id": 273 }, { "name": "minecraft:cookie", - "id": 272 + "id": 275 }, { "name": "minecraft:copper_block", @@ -1157,7 +1209,7 @@ }, { "name": "minecraft:copper_ingot", - "id": 515 + "id": 520 }, { "name": "minecraft:copper_ore", @@ -1169,19 +1221,19 @@ }, { "name": "minecraft:coral", - "id": 719 + "id": 740 }, { "name": "minecraft:coral_block", - "id": -132 + "id": 729 }, { "name": "minecraft:coral_fan", - "id": -133 + "id": 730 }, { "name": "minecraft:coral_fan_dead", - "id": -134 + "id": 731 }, { "name": "minecraft:coral_fan_hang", @@ -1195,9 +1247,13 @@ "name": "minecraft:coral_fan_hang3", "id": -137 }, + { + "name": "minecraft:cornflower", + "id": -838 + }, { "name": "minecraft:cow_spawn_egg", - "id": 440 + "id": 445 }, { "name": "minecraft:cracked_deepslate_bricks", @@ -1225,11 +1281,11 @@ }, { "name": "minecraft:creeper_banner_pattern", - "id": 593 + "id": 598 }, { "name": "minecraft:creeper_spawn_egg", - "id": 445 + "id": 450 }, { "name": "minecraft:crimson_button", @@ -1237,7 +1293,7 @@ }, { "name": "minecraft:crimson_door", - "id": 627 + "id": 635 }, { "name": "minecraft:crimson_double_slab", @@ -1281,7 +1337,7 @@ }, { "name": "minecraft:crimson_sign", - "id": 625 + "id": 633 }, { "name": "minecraft:crimson_slab", @@ -1309,7 +1365,7 @@ }, { "name": "minecraft:crossbow", - "id": 586 + "id": 591 }, { "name": "minecraft:crying_obsidian", @@ -1349,7 +1405,7 @@ }, { "name": "minecraft:cyan_dye", - "id": 405 + "id": 409 }, { "name": "minecraft:cyan_glazed_terracotta", @@ -1377,11 +1433,11 @@ }, { "name": "minecraft:danger_pottery_sherd", - "id": 673 + "id": 681 }, { "name": "minecraft:dark_oak_boat", - "id": 384 + "id": 388 }, { "name": "minecraft:dark_oak_button", @@ -1389,11 +1445,11 @@ }, { "name": "minecraft:dark_oak_chest_boat", - "id": 654 + "id": 662 }, { "name": "minecraft:dark_oak_door", - "id": 568 + "id": 573 }, { "name": "minecraft:dark_oak_double_slab", @@ -1427,9 +1483,13 @@ "name": "minecraft:dark_oak_pressure_plate", "id": -152 }, + { + "name": "minecraft:dark_oak_sapling", + "id": -829 + }, { "name": "minecraft:dark_oak_sign", - "id": 591 + "id": 596 }, { "name": "minecraft:dark_oak_slab", @@ -1471,22 +1531,62 @@ "name": "minecraft:dead_brain_coral", "id": -586 }, + { + "name": "minecraft:dead_brain_coral_block", + "id": -854 + }, + { + "name": "minecraft:dead_brain_coral_fan", + "id": -844 + }, { "name": "minecraft:dead_bubble_coral", "id": -587 }, + { + "name": "minecraft:dead_bubble_coral_block", + "id": -855 + }, + { + "name": "minecraft:dead_bubble_coral_fan", + "id": -845 + }, { "name": "minecraft:dead_fire_coral", "id": -588 }, + { + "name": "minecraft:dead_fire_coral_block", + "id": -856 + }, + { + "name": "minecraft:dead_fire_coral_fan", + "id": -846 + }, { "name": "minecraft:dead_horn_coral", "id": -589 }, + { + "name": "minecraft:dead_horn_coral_block", + "id": -857 + }, + { + "name": "minecraft:dead_horn_coral_fan", + "id": -847 + }, { "name": "minecraft:dead_tube_coral", "id": -585 }, + { + "name": "minecraft:dead_tube_coral_block", + "id": -853 + }, + { + "name": "minecraft:dead_tube_coral_fan", + "id": -134 + }, { "name": "minecraft:deadbush", "id": 32 @@ -1581,11 +1681,11 @@ }, { "name": "minecraft:diamond", - "id": 307 + "id": 310 }, { "name": "minecraft:diamond_axe", - "id": 322 + "id": 325 }, { "name": "minecraft:diamond_block", @@ -1593,27 +1693,27 @@ }, { "name": "minecraft:diamond_boots", - "id": 353 + "id": 357 }, { "name": "minecraft:diamond_chestplate", - "id": 351 + "id": 355 }, { "name": "minecraft:diamond_helmet", - "id": 350 + "id": 354 }, { "name": "minecraft:diamond_hoe", - "id": 335 + "id": 339 }, { "name": "minecraft:diamond_horse_armor", - "id": 544 + "id": 549 }, { "name": "minecraft:diamond_leggings", - "id": 352 + "id": 356 }, { "name": "minecraft:diamond_ore", @@ -1621,15 +1721,15 @@ }, { "name": "minecraft:diamond_pickaxe", - "id": 321 + "id": 324 }, { "name": "minecraft:diamond_shovel", - "id": 320 + "id": 323 }, { "name": "minecraft:diamond_sword", - "id": 319 + "id": 322 }, { "name": "minecraft:diorite", @@ -1649,7 +1749,7 @@ }, { "name": "minecraft:disc_fragment_5", - "id": 648 + "id": 656 }, { "name": "minecraft:dispenser", @@ -1657,11 +1757,11 @@ }, { "name": "minecraft:dolphin_spawn_egg", - "id": 489 + "id": 494 }, { "name": "minecraft:donkey_spawn_egg", - "id": 470 + "id": 475 }, { "name": "minecraft:double_cut_copper_slab", @@ -1669,7 +1769,7 @@ }, { "name": "minecraft:double_plant", - "id": 175 + "id": 738 }, { "name": "minecraft:double_stone_block_slab", @@ -1689,7 +1789,7 @@ }, { "name": "minecraft:dragon_breath", - "id": 571 + "id": 576 }, { "name": "minecraft:dragon_egg", @@ -1697,7 +1797,7 @@ }, { "name": "minecraft:dried_kelp", - "id": 271 + "id": 274 }, { "name": "minecraft:dried_kelp_block", @@ -1713,27 +1813,27 @@ }, { "name": "minecraft:drowned_spawn_egg", - "id": 488 + "id": 493 }, { "name": "minecraft:dune_armor_trim_smithing_template", - "id": 690 + "id": 701 }, { "name": "minecraft:dye", - "id": 730 + "id": 755 }, { "name": "minecraft:echo_shard", - "id": 658 + "id": 666 }, { "name": "minecraft:egg", - "id": 394 + "id": 398 }, { "name": "minecraft:elder_guardian_spawn_egg", - "id": 476 + "id": 481 }, { "name": "minecraft:element_0", @@ -2213,11 +2313,11 @@ }, { "name": "minecraft:elytra", - "id": 575 + "id": 580 }, { "name": "minecraft:emerald", - "id": 523 + "id": 528 }, { "name": "minecraft:emerald_block", @@ -2229,15 +2329,15 @@ }, { "name": "minecraft:empty_map", - "id": 526 + "id": 531 }, { "name": "minecraft:enchanted_book", - "id": 532 + "id": 537 }, { "name": "minecraft:enchanted_golden_apple", - "id": 260 + "id": 263 }, { "name": "minecraft:enchanting_table", @@ -2253,7 +2353,7 @@ }, { "name": "minecraft:end_crystal", - "id": 733 + "id": 758 }, { "name": "minecraft:end_gateway", @@ -2281,35 +2381,35 @@ }, { "name": "minecraft:ender_dragon_spawn_egg", - "id": 512 + "id": 517 }, { "name": "minecraft:ender_eye", - "id": 437 + "id": 442 }, { "name": "minecraft:ender_pearl", - "id": 426 + "id": 430 }, { "name": "minecraft:enderman_spawn_egg", - "id": 446 + "id": 451 }, { "name": "minecraft:endermite_spawn_egg", - "id": 464 + "id": 469 }, { "name": "minecraft:evoker_spawn_egg", - "id": 480 + "id": 485 }, { "name": "minecraft:experience_bottle", - "id": 519 + "id": 524 }, { "name": "minecraft:explorer_pottery_sherd", - "id": 674 + "id": 682 }, { "name": "minecraft:exposed_chiseled_copper", @@ -2353,7 +2453,7 @@ }, { "name": "minecraft:eye_armor_trim_smithing_template", - "id": 694 + "id": 705 }, { "name": "minecraft:farmland", @@ -2361,11 +2461,11 @@ }, { "name": "minecraft:feather", - "id": 330 + "id": 334 }, { "name": "minecraft:fence", - "id": 714 + "id": 728 }, { "name": "minecraft:fence_gate", @@ -2373,15 +2473,19 @@ }, { "name": "minecraft:fermented_spider_eye", - "id": 432 + "id": 437 + }, + { + "name": "minecraft:fern", + "id": -848 }, { "name": "minecraft:field_masoned_banner_pattern", - "id": 596 + "id": 601 }, { "name": "minecraft:filled_map", - "id": 424 + "id": 428 }, { "name": "minecraft:fire", @@ -2389,23 +2493,31 @@ }, { "name": "minecraft:fire_charge", - "id": 520 + "id": 525 }, { "name": "minecraft:fire_coral", "id": -583 }, + { + "name": "minecraft:fire_coral_block", + "id": -851 + }, + { + "name": "minecraft:fire_coral_fan", + "id": -842 + }, { "name": "minecraft:firework_rocket", - "id": 530 + "id": 535 }, { "name": "minecraft:firework_star", - "id": 531 + "id": 536 }, { "name": "minecraft:fishing_rod", - "id": 396 + "id": 400 }, { "name": "minecraft:fletching_table", @@ -2413,19 +2525,31 @@ }, { "name": "minecraft:flint", - "id": 359 + "id": 363 }, { "name": "minecraft:flint_and_steel", - "id": 302 + "id": 305 + }, + { + "name": "minecraft:flow_armor_trim_smithing_template", + "id": 716 + }, + { + "name": "minecraft:flow_banner_pattern", + "id": 605 + }, + { + "name": "minecraft:flow_pottery_sherd", + "id": 683 }, { "name": "minecraft:flower_banner_pattern", - "id": 592 + "id": 597 }, { "name": "minecraft:flower_pot", - "id": 525 + "id": 530 }, { "name": "minecraft:flowering_azalea", @@ -2441,15 +2565,15 @@ }, { "name": "minecraft:fox_spawn_egg", - "id": 495 + "id": 500 }, { "name": "minecraft:frame", - "id": 524 + "id": 529 }, { "name": "minecraft:friend_pottery_sherd", - "id": 675 + "id": 684 }, { "name": "minecraft:frog_spawn", @@ -2457,7 +2581,7 @@ }, { "name": "minecraft:frog_spawn_egg", - "id": 639 + "id": 647 }, { "name": "minecraft:frosted_ice", @@ -2469,11 +2593,11 @@ }, { "name": "minecraft:ghast_spawn_egg", - "id": 458 + "id": 463 }, { "name": "minecraft:ghast_tear", - "id": 428 + "id": 433 }, { "name": "minecraft:gilded_blackstone", @@ -2485,7 +2609,7 @@ }, { "name": "minecraft:glass_bottle", - "id": 431 + "id": 436 }, { "name": "minecraft:glass_pane", @@ -2493,23 +2617,23 @@ }, { "name": "minecraft:glistering_melon_slice", - "id": 438 + "id": 443 }, { "name": "minecraft:globe_banner_pattern", - "id": 599 + "id": 604 }, { "name": "minecraft:glow_berries", - "id": 734 + "id": 759 }, { "name": "minecraft:glow_frame", - "id": 634 + "id": 642 }, { "name": "minecraft:glow_ink_sac", - "id": 514 + "id": 519 }, { "name": "minecraft:glow_lichen", @@ -2517,11 +2641,11 @@ }, { "name": "minecraft:glow_squid_spawn_egg", - "id": 509 + "id": 514 }, { "name": "minecraft:glow_stick", - "id": 612 + "id": 620 }, { "name": "minecraft:glowingobsidian", @@ -2533,15 +2657,15 @@ }, { "name": "minecraft:glowstone_dust", - "id": 398 + "id": 402 }, { "name": "minecraft:goat_horn", - "id": 638 + "id": 646 }, { "name": "minecraft:goat_spawn_egg", - "id": 508 + "id": 513 }, { "name": "minecraft:gold_block", @@ -2549,11 +2673,11 @@ }, { "name": "minecraft:gold_ingot", - "id": 309 + "id": 312 }, { "name": "minecraft:gold_nugget", - "id": 429 + "id": 434 }, { "name": "minecraft:gold_ore", @@ -2561,43 +2685,43 @@ }, { "name": "minecraft:golden_apple", - "id": 259 + "id": 262 }, { "name": "minecraft:golden_axe", - "id": 328 + "id": 332 }, { "name": "minecraft:golden_boots", - "id": 357 + "id": 361 }, { "name": "minecraft:golden_carrot", - "id": 284 + "id": 287 }, { "name": "minecraft:golden_chestplate", - "id": 355 + "id": 359 }, { "name": "minecraft:golden_helmet", - "id": 354 + "id": 358 }, { "name": "minecraft:golden_hoe", - "id": 336 + "id": 340 }, { "name": "minecraft:golden_horse_armor", - "id": 543 + "id": 548 }, { "name": "minecraft:golden_leggings", - "id": 356 + "id": 360 }, { "name": "minecraft:golden_pickaxe", - "id": 327 + "id": 331 }, { "name": "minecraft:golden_rail", @@ -2605,11 +2729,11 @@ }, { "name": "minecraft:golden_shovel", - "id": 326 + "id": 330 }, { "name": "minecraft:golden_sword", - "id": 325 + "id": 329 }, { "name": "minecraft:granite", @@ -2653,7 +2777,7 @@ }, { "name": "minecraft:gray_dye", - "id": 407 + "id": 411 }, { "name": "minecraft:gray_glazed_terracotta", @@ -2701,7 +2825,7 @@ }, { "name": "minecraft:green_dye", - "id": 401 + "id": 405 }, { "name": "minecraft:green_glazed_terracotta", @@ -2733,11 +2857,19 @@ }, { "name": "minecraft:guardian_spawn_egg", - "id": 465 + "id": 470 }, { "name": "minecraft:gunpowder", - "id": 331 + "id": 335 + }, + { + "name": "minecraft:guster_banner_pattern", + "id": 606 + }, + { + "name": "minecraft:guster_pottery_sherd", + "id": 685 }, { "name": "minecraft:hanging_roots", @@ -2865,11 +2997,11 @@ }, { "name": "minecraft:hard_stained_glass", - "id": 727 + "id": 752 }, { "name": "minecraft:hard_stained_glass_pane", - "id": 728 + "id": 753 }, { "name": "minecraft:hard_white_stained_glass", @@ -2897,15 +3029,19 @@ }, { "name": "minecraft:heart_of_the_sea", - "id": 582 + "id": 587 }, { "name": "minecraft:heart_pottery_sherd", - "id": 676 + "id": 686 }, { "name": "minecraft:heartbreak_pottery_sherd", - "id": 677 + "id": 687 + }, + { + "name": "minecraft:heavy_core", + "id": -316 }, { "name": "minecraft:heavy_weighted_pressure_plate", @@ -2913,7 +3049,7 @@ }, { "name": "minecraft:hoglin_spawn_egg", - "id": 501 + "id": 506 }, { "name": "minecraft:honey_block", @@ -2921,11 +3057,11 @@ }, { "name": "minecraft:honey_bottle", - "id": 603 + "id": 610 }, { "name": "minecraft:honeycomb", - "id": 602 + "id": 609 }, { "name": "minecraft:honeycomb_block", @@ -2933,31 +3069,39 @@ }, { "name": "minecraft:hopper", - "id": 538 + "id": 543 }, { "name": "minecraft:hopper_minecart", - "id": 537 + "id": 542 }, { "name": "minecraft:horn_coral", "id": -584 }, + { + "name": "minecraft:horn_coral_block", + "id": -852 + }, + { + "name": "minecraft:horn_coral_fan", + "id": -843 + }, { "name": "minecraft:horse_spawn_egg", - "id": 462 + "id": 467 }, { "name": "minecraft:host_armor_trim_smithing_template", - "id": 704 + "id": 715 }, { "name": "minecraft:howl_pottery_sherd", - "id": 678 + "id": 688 }, { "name": "minecraft:husk_spawn_egg", - "id": 468 + "id": 473 }, { "name": "minecraft:ice", @@ -2965,7 +3109,7 @@ }, { "name": "minecraft:ice_bomb", - "id": 606 + "id": 614 }, { "name": "minecraft:infested_deepslate", @@ -2981,7 +3125,7 @@ }, { "name": "minecraft:ink_sac", - "id": 417 + "id": 421 }, { "name": "minecraft:invisible_bedrock", @@ -2989,7 +3133,7 @@ }, { "name": "minecraft:iron_axe", - "id": 301 + "id": 304 }, { "name": "minecraft:iron_bars", @@ -3001,43 +3145,43 @@ }, { "name": "minecraft:iron_boots", - "id": 349 + "id": 353 }, { "name": "minecraft:iron_chestplate", - "id": 347 + "id": 351 }, { "name": "minecraft:iron_door", - "id": 375 + "id": 379 }, { "name": "minecraft:iron_golem_spawn_egg", - "id": 510 + "id": 515 }, { "name": "minecraft:iron_helmet", - "id": 346 + "id": 350 }, { "name": "minecraft:iron_hoe", - "id": 334 + "id": 338 }, { "name": "minecraft:iron_horse_armor", - "id": 542 + "id": 547 }, { "name": "minecraft:iron_ingot", - "id": 308 + "id": 311 }, { "name": "minecraft:iron_leggings", - "id": 348 + "id": 352 }, { "name": "minecraft:iron_nugget", - "id": 580 + "id": 585 }, { "name": "minecraft:iron_ore", @@ -3045,15 +3189,15 @@ }, { "name": "minecraft:iron_pickaxe", - "id": 300 + "id": 303 }, { "name": "minecraft:iron_shovel", - "id": 299 + "id": 302 }, { "name": "minecraft:iron_sword", - "id": 310 + "id": 313 }, { "name": "minecraft:iron_trapdoor", @@ -3185,7 +3329,7 @@ }, { "name": "minecraft:jungle_boat", - "id": 381 + "id": 385 }, { "name": "minecraft:jungle_button", @@ -3193,11 +3337,11 @@ }, { "name": "minecraft:jungle_chest_boat", - "id": 651 + "id": 659 }, { "name": "minecraft:jungle_door", - "id": 566 + "id": 571 }, { "name": "minecraft:jungle_double_slab", @@ -3231,9 +3375,13 @@ "name": "minecraft:jungle_pressure_plate", "id": -153 }, + { + "name": "minecraft:jungle_sapling", + "id": -827 + }, { "name": "minecraft:jungle_sign", - "id": 589 + "id": 594 }, { "name": "minecraft:jungle_slab", @@ -3261,7 +3409,7 @@ }, { "name": "minecraft:kelp", - "id": 386 + "id": 390 }, { "name": "minecraft:ladder", @@ -3277,7 +3425,7 @@ }, { "name": "minecraft:lapis_lazuli", - "id": 418 + "id": 422 }, { "name": "minecraft:lapis_ore", @@ -3287,49 +3435,53 @@ "name": "minecraft:large_amethyst_bud", "id": -330 }, + { + "name": "minecraft:large_fern", + "id": -865 + }, { "name": "minecraft:lava", "id": 11 }, { "name": "minecraft:lava_bucket", - "id": 366 + "id": 370 }, { "name": "minecraft:lead", - "id": 558 + "id": 563 }, { "name": "minecraft:leather", - "id": 385 + "id": 389 }, { "name": "minecraft:leather_boots", - "id": 341 + "id": 345 }, { "name": "minecraft:leather_chestplate", - "id": 339 + "id": 343 }, { "name": "minecraft:leather_helmet", - "id": 338 + "id": 342 }, { "name": "minecraft:leather_horse_armor", - "id": 541 + "id": 546 }, { "name": "minecraft:leather_leggings", - "id": 340 + "id": 344 }, { "name": "minecraft:leaves", - "id": 715 + "id": 733 }, { "name": "minecraft:leaves2", - "id": 716 + "id": 734 }, { "name": "minecraft:lectern", @@ -3365,7 +3517,7 @@ }, { "name": "minecraft:light_blue_dye", - "id": 411 + "id": 415 }, { "name": "minecraft:light_blue_glazed_terracotta", @@ -3413,7 +3565,7 @@ }, { "name": "minecraft:light_gray_dye", - "id": 406 + "id": 410 }, { "name": "minecraft:light_gray_shulker_box", @@ -3443,6 +3595,14 @@ "name": "minecraft:lightning_rod", "id": -312 }, + { + "name": "minecraft:lilac", + "id": -863 + }, + { + "name": "minecraft:lily_of_the_valley", + "id": -839 + }, { "name": "minecraft:lime_candle", "id": -418 @@ -3465,7 +3625,7 @@ }, { "name": "minecraft:lime_dye", - "id": 409 + "id": 413 }, { "name": "minecraft:lime_glazed_terracotta", @@ -3493,7 +3653,7 @@ }, { "name": "minecraft:lingering_potion", - "id": 573 + "id": 578 }, { "name": "minecraft:lit_blast_furnace", @@ -3525,7 +3685,7 @@ }, { "name": "minecraft:llama_spawn_egg", - "id": 478 + "id": 483 }, { "name": "minecraft:lodestone", @@ -3533,20 +3693,24 @@ }, { "name": "minecraft:lodestone_compass", - "id": 613 + "id": 621 }, { "name": "minecraft:log", - "id": 713 + "id": 727 }, { "name": "minecraft:log2", - "id": 720 + "id": 742 }, { "name": "minecraft:loom", "id": -204 }, + { + "name": "minecraft:mace", + "id": 326 + }, { "name": "minecraft:magenta_candle", "id": -415 @@ -3569,7 +3733,7 @@ }, { "name": "minecraft:magenta_dye", - "id": 412 + "id": 416 }, { "name": "minecraft:magenta_glazed_terracotta", @@ -3601,15 +3765,15 @@ }, { "name": "minecraft:magma_cream", - "id": 434 + "id": 439 }, { "name": "minecraft:magma_cube_spawn_egg", - "id": 459 + "id": 464 }, { "name": "minecraft:mangrove_boat", - "id": 646 + "id": 654 }, { "name": "minecraft:mangrove_button", @@ -3617,11 +3781,11 @@ }, { "name": "minecraft:mangrove_chest_boat", - "id": 655 + "id": 663 }, { "name": "minecraft:mangrove_door", - "id": 644 + "id": 652 }, { "name": "minecraft:mangrove_double_slab", @@ -3665,7 +3829,7 @@ }, { "name": "minecraft:mangrove_sign", - "id": 645 + "id": 653 }, { "name": "minecraft:mangrove_slab", @@ -3693,7 +3857,7 @@ }, { "name": "minecraft:medicine", - "id": 610 + "id": 618 }, { "name": "minecraft:medium_amethyst_bud", @@ -3705,11 +3869,11 @@ }, { "name": "minecraft:melon_seeds", - "id": 294 + "id": 297 }, { "name": "minecraft:melon_slice", - "id": 273 + "id": 276 }, { "name": "minecraft:melon_stem", @@ -3717,15 +3881,15 @@ }, { "name": "minecraft:milk_bucket", - "id": 364 + "id": 368 }, { "name": "minecraft:minecart", - "id": 373 + "id": 377 }, { "name": "minecraft:miner_pottery_sherd", - "id": 679 + "id": 689 }, { "name": "minecraft:mob_spawner", @@ -3733,7 +3897,7 @@ }, { "name": "minecraft:mojang_banner_pattern", - "id": 595 + "id": 600 }, { "name": "minecraft:monster_egg", @@ -3741,7 +3905,7 @@ }, { "name": "minecraft:mooshroom_spawn_egg", - "id": 444 + "id": 449 }, { "name": "minecraft:moss_block", @@ -3765,7 +3929,7 @@ }, { "name": "minecraft:mourner_pottery_sherd", - "id": 680 + "id": 690 }, { "name": "minecraft:moving_block", @@ -3801,91 +3965,103 @@ }, { "name": "minecraft:mule_spawn_egg", - "id": 471 + "id": 476 }, { "name": "minecraft:mushroom_stew", - "id": 261 + "id": 264 }, { "name": "minecraft:music_disc_11", - "id": 555 + "id": 560 }, { "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_5", + "id": 655 }, { - "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", + "name": "minecraft:music_disc_blocks", "id": 552 }, { - "name": "minecraft:music_disc_strad", + "name": "minecraft:music_disc_cat", + "id": 551 + }, + { + "name": "minecraft:music_disc_chirp", "id": 553 }, { - "name": "minecraft:music_disc_wait", - "id": 556 + "name": "minecraft:music_disc_creator", + "id": 749 }, { - "name": "minecraft:music_disc_ward", + "name": "minecraft:music_disc_creator_music_box", + "id": 750 + }, + { + "name": "minecraft:music_disc_far", "id": 554 }, { - "name": "minecraft:mutton", + "name": "minecraft:music_disc_mall", + "id": 555 + }, + { + "name": "minecraft:music_disc_mellohi", + "id": 556 + }, + { + "name": "minecraft:music_disc_otherside", + "id": 645 + }, + { + "name": "minecraft:music_disc_pigstep", + "id": 639 + }, + { + "name": "minecraft:music_disc_precipice", + "id": 751 + }, + { + "name": "minecraft:music_disc_relic", + "id": 718 + }, + { + "name": "minecraft:music_disc_stal", + "id": 557 + }, + { + "name": "minecraft:music_disc_strad", + "id": 558 + }, + { + "name": "minecraft:music_disc_wait", "id": 561 }, + { + "name": "minecraft:music_disc_ward", + "id": 559 + }, + { + "name": "minecraft:mutton", + "id": 566 + }, { "name": "minecraft:mycelium", "id": 110 }, { "name": "minecraft:name_tag", - "id": 559 + "id": 564 }, { "name": "minecraft:nautilus_shell", - "id": 581 + "id": 586 }, { "name": "minecraft:nether_brick", @@ -3895,6 +4071,10 @@ "name": "minecraft:nether_brick_fence", "id": 113 }, + { + "name": "minecraft:nether_brick_slab", + "id": -877 + }, { "name": "minecraft:nether_brick_stairs", "id": 114 @@ -3905,15 +4085,15 @@ }, { "name": "minecraft:nether_sprouts", - "id": 632 + "id": 640 }, { "name": "minecraft:nether_star", - "id": 529 + "id": 534 }, { "name": "minecraft:nether_wart", - "id": 295 + "id": 298 }, { "name": "minecraft:nether_wart_block", @@ -3921,11 +4101,11 @@ }, { "name": "minecraft:netherbrick", - "id": 534 + "id": 539 }, { "name": "minecraft:netherite_axe", - "id": 617 + "id": 625 }, { "name": "minecraft:netherite_block", @@ -3933,47 +4113,47 @@ }, { "name": "minecraft:netherite_boots", - "id": 623 + "id": 631 }, { "name": "minecraft:netherite_chestplate", - "id": 621 + "id": 629 }, { "name": "minecraft:netherite_helmet", - "id": 620 + "id": 628 }, { "name": "minecraft:netherite_hoe", - "id": 618 + "id": 626 }, { "name": "minecraft:netherite_ingot", - "id": 619 + "id": 627 }, { "name": "minecraft:netherite_leggings", - "id": 622 + "id": 630 }, { "name": "minecraft:netherite_pickaxe", - "id": 616 - }, - { - "name": "minecraft:netherite_scrap", "id": 624 }, + { + "name": "minecraft:netherite_scrap", + "id": 632 + }, { "name": "minecraft:netherite_shovel", - "id": 615 + "id": 623 }, { "name": "minecraft:netherite_sword", - "id": 614 + "id": 622 }, { "name": "minecraft:netherite_upgrade_smithing_template", - "id": 688 + "id": 699 }, { "name": "minecraft:netherrack", @@ -3993,15 +4173,15 @@ }, { "name": "minecraft:npc_spawn_egg", - "id": 475 + "id": 480 }, { "name": "minecraft:oak_boat", - "id": 379 + "id": 383 }, { "name": "minecraft:oak_chest_boat", - "id": 649 + "id": 657 }, { "name": "minecraft:oak_double_slab", @@ -4027,9 +4207,13 @@ "name": "minecraft:oak_planks", "id": 5 }, + { + "name": "minecraft:oak_sapling", + "id": 6 + }, { "name": "minecraft:oak_sign", - "id": 361 + "id": 365 }, { "name": "minecraft:oak_slab", @@ -4053,12 +4237,20 @@ }, { "name": "minecraft:ocelot_spawn_egg", - "id": 455 + "id": 460 }, { "name": "minecraft:ochre_froglight", "id": -471 }, + { + "name": "minecraft:ominous_bottle", + "id": 611 + }, + { + "name": "minecraft:ominous_trial_key", + "id": 258 + }, { "name": "minecraft:orange_candle", "id": -414 @@ -4081,7 +4273,7 @@ }, { "name": "minecraft:orange_dye", - "id": 413 + "id": 417 }, { "name": "minecraft:orange_glazed_terracotta", @@ -4103,10 +4295,18 @@ "name": "minecraft:orange_terracotta", "id": -724 }, + { + "name": "minecraft:orange_tulip", + "id": -834 + }, { "name": "minecraft:orange_wool", "id": -557 }, + { + "name": "minecraft:oxeye_daisy", + "id": -837 + }, { "name": "minecraft:oxidized_chiseled_copper", "id": -763 @@ -4157,51 +4357,59 @@ }, { "name": "minecraft:painting", - "id": 360 + "id": 364 }, { "name": "minecraft:panda_spawn_egg", - "id": 494 + "id": 499 }, { "name": "minecraft:paper", - "id": 390 + "id": 394 }, { "name": "minecraft:parrot_spawn_egg", - "id": 483 + "id": 488 }, { "name": "minecraft:pearlescent_froglight", "id": -469 }, + { + "name": "minecraft:peony", + "id": -867 + }, + { + "name": "minecraft:petrified_oak_slab", + "id": -902 + }, { "name": "minecraft:phantom_membrane", - "id": 585 + "id": 590 }, { "name": "minecraft:phantom_spawn_egg", - "id": 491 + "id": 496 }, { "name": "minecraft:pig_spawn_egg", - "id": 441 + "id": 446 }, { "name": "minecraft:piglin_banner_pattern", - "id": 598 + "id": 603 }, { "name": "minecraft:piglin_brute_spawn_egg", - "id": 504 + "id": 509 }, { "name": "minecraft:piglin_spawn_egg", - "id": 502 + "id": 507 }, { "name": "minecraft:pillager_spawn_egg", - "id": 496 + "id": 501 }, { "name": "minecraft:pink_candle", @@ -4225,7 +4433,7 @@ }, { "name": "minecraft:pink_dye", - "id": 408 + "id": 412 }, { "name": "minecraft:pink_glazed_terracotta", @@ -4251,6 +4459,10 @@ "name": "minecraft:pink_terracotta", "id": -729 }, + { + "name": "minecraft:pink_tulip", + "id": -836 + }, { "name": "minecraft:pink_wool", "id": -566 @@ -4273,15 +4485,15 @@ }, { "name": "minecraft:pitcher_pod", - "id": 298 + "id": 301 }, { "name": "minecraft:planks", - "id": 718 + "id": 739 }, { "name": "minecraft:plenty_pottery_sherd", - "id": 681 + "id": 691 }, { "name": "minecraft:podzol", @@ -4293,11 +4505,11 @@ }, { "name": "minecraft:poisonous_potato", - "id": 283 + "id": 286 }, { "name": "minecraft:polar_bear_spawn_egg", - "id": 477 + "id": 482 }, { "name": "minecraft:polished_andesite", @@ -4417,11 +4629,15 @@ }, { "name": "minecraft:popped_chorus_fruit", - "id": 570 + "id": 575 + }, + { + "name": "minecraft:poppy", + "id": 38 }, { "name": "minecraft:porkchop", - "id": 263 + "id": 266 }, { "name": "minecraft:portal", @@ -4429,7 +4645,7 @@ }, { "name": "minecraft:potato", - "id": 281 + "id": 284 }, { "name": "minecraft:potatoes", @@ -4437,7 +4653,7 @@ }, { "name": "minecraft:potion", - "id": 430 + "id": 435 }, { "name": "minecraft:powder_snow", @@ -4445,7 +4661,7 @@ }, { "name": "minecraft:powder_snow_bucket", - "id": 371 + "id": 375 }, { "name": "minecraft:powered_comparator", @@ -4465,11 +4681,11 @@ }, { "name": "minecraft:prismarine_crystals", - "id": 560 + "id": 565 }, { "name": "minecraft:prismarine_shard", - "id": 576 + "id": 581 }, { "name": "minecraft:prismarine_stairs", @@ -4477,19 +4693,19 @@ }, { "name": "minecraft:prize_pottery_sherd", - "id": 682 + "id": 692 }, { "name": "minecraft:pufferfish", - "id": 268 + "id": 271 }, { "name": "minecraft:pufferfish_bucket", - "id": 370 + "id": 374 }, { "name": "minecraft:pufferfish_spawn_egg", - "id": 486 + "id": 491 }, { "name": "minecraft:pumpkin", @@ -4497,11 +4713,11 @@ }, { "name": "minecraft:pumpkin_pie", - "id": 285 + "id": 288 }, { "name": "minecraft:pumpkin_seeds", - "id": 293 + "id": 296 }, { "name": "minecraft:pumpkin_stem", @@ -4529,7 +4745,7 @@ }, { "name": "minecraft:purple_dye", - "id": 404 + "id": 408 }, { "name": "minecraft:purple_glazed_terracotta", @@ -4565,7 +4781,7 @@ }, { "name": "minecraft:quartz", - "id": 535 + "id": 540 }, { "name": "minecraft:quartz_block", @@ -4579,29 +4795,33 @@ "name": "minecraft:quartz_ore", "id": 153 }, + { + "name": "minecraft:quartz_slab", + "id": -876 + }, { "name": "minecraft:quartz_stairs", "id": 156 }, { "name": "minecraft:rabbit", - "id": 289 + "id": 292 }, { "name": "minecraft:rabbit_foot", - "id": 539 + "id": 544 }, { "name": "minecraft:rabbit_hide", - "id": 540 + "id": 545 }, { "name": "minecraft:rabbit_spawn_egg", - "id": 463 + "id": 468 }, { "name": "minecraft:rabbit_stew", - "id": 291 + "id": 294 }, { "name": "minecraft:rail", @@ -4609,19 +4829,19 @@ }, { "name": "minecraft:raiser_armor_trim_smithing_template", - "id": 702 + "id": 713 }, { "name": "minecraft:rapid_fertilizer", - "id": 608 + "id": 616 }, { "name": "minecraft:ravager_spawn_egg", - "id": 498 + "id": 503 }, { "name": "minecraft:raw_copper", - "id": 518 + "id": 523 }, { "name": "minecraft:raw_copper_block", @@ -4629,7 +4849,7 @@ }, { "name": "minecraft:raw_gold", - "id": 517 + "id": 522 }, { "name": "minecraft:raw_gold_block", @@ -4637,7 +4857,7 @@ }, { "name": "minecraft:raw_iron", - "id": 516 + "id": 521 }, { "name": "minecraft:raw_iron_block", @@ -4645,7 +4865,7 @@ }, { "name": "minecraft:recovery_compass", - "id": 657 + "id": 665 }, { "name": "minecraft:red_candle", @@ -4669,11 +4889,11 @@ }, { "name": "minecraft:red_dye", - "id": 400 + "id": 404 }, { "name": "minecraft:red_flower", - "id": 38 + "id": 737 }, { "name": "minecraft:red_glazed_terracotta", @@ -4719,13 +4939,17 @@ "name": "minecraft:red_terracotta", "id": -737 }, + { + "name": "minecraft:red_tulip", + "id": -833 + }, { "name": "minecraft:red_wool", "id": -556 }, { "name": "minecraft:redstone", - "id": 376 + "id": 380 }, { "name": "minecraft:redstone_block", @@ -4753,7 +4977,7 @@ }, { "name": "minecraft:repeater", - "id": 423 + "id": 427 }, { "name": "minecraft:repeating_command_block", @@ -4769,27 +4993,31 @@ }, { "name": "minecraft:rib_armor_trim_smithing_template", - "id": 698 + "id": 709 + }, + { + "name": "minecraft:rose_bush", + "id": -866 }, { "name": "minecraft:rotten_flesh", - "id": 278 + "id": 281 }, { "name": "minecraft:saddle", - "id": 374 + "id": 378 }, { "name": "minecraft:salmon", - "id": 266 + "id": 269 }, { "name": "minecraft:salmon_bucket", - "id": 368 + "id": 372 }, { "name": "minecraft:salmon_spawn_egg", - "id": 487 + "id": 492 }, { "name": "minecraft:sand", @@ -4799,18 +5027,26 @@ "name": "minecraft:sandstone", "id": 24 }, + { + "name": "minecraft:sandstone_slab", + "id": -872 + }, { "name": "minecraft:sandstone_stairs", "id": 128 }, { "name": "minecraft:sapling", - "id": 6 + "id": 732 }, { "name": "minecraft:scaffolding", "id": -165 }, + { + "name": "minecraft:scrape_pottery_sherd", + "id": 693 + }, { "name": "minecraft:sculk", "id": -458 @@ -4845,31 +5081,35 @@ }, { "name": "minecraft:sentry_armor_trim_smithing_template", - "id": 689 + "id": 700 }, { "name": "minecraft:shaper_armor_trim_smithing_template", - "id": 703 + "id": 714 }, { "name": "minecraft:sheaf_pottery_sherd", - "id": 683 + "id": 694 }, { "name": "minecraft:shears", - "id": 425 + "id": 429 }, { "name": "minecraft:sheep_spawn_egg", - "id": 442 + "id": 447 }, { "name": "minecraft:shelter_pottery_sherd", - "id": 684 + "id": 695 }, { "name": "minecraft:shield", - "id": 358 + "id": 362 + }, + { + "name": "minecraft:short_grass", + "id": 31 }, { "name": "minecraft:shroomlight", @@ -4877,19 +5117,19 @@ }, { "name": "minecraft:shulker_box", - "id": 725 + "id": 747 }, { "name": "minecraft:shulker_shell", - "id": 577 + "id": 582 }, { "name": "minecraft:shulker_spawn_egg", - "id": 474 + "id": 479 }, { "name": "minecraft:silence_armor_trim_smithing_template", - "id": 700 + "id": 711 }, { "name": "minecraft:silver_glazed_terracotta", @@ -4897,27 +5137,27 @@ }, { "name": "minecraft:silverfish_spawn_egg", - "id": 447 + "id": 452 }, { "name": "minecraft:skeleton_horse_spawn_egg", - "id": 472 + "id": 477 }, { "name": "minecraft:skeleton_spawn_egg", - "id": 448 + "id": 453 }, { "name": "minecraft:skull", - "id": 527 + "id": 532 }, { "name": "minecraft:skull_banner_pattern", - "id": 594 + "id": 599 }, { "name": "minecraft:skull_pottery_sherd", - "id": 685 + "id": 696 }, { "name": "minecraft:slime", @@ -4925,11 +5165,11 @@ }, { "name": "minecraft:slime_ball", - "id": 392 + "id": 396 }, { "name": "minecraft:slime_spawn_egg", - "id": 449 + "id": 454 }, { "name": "minecraft:small_amethyst_bud", @@ -4967,21 +5207,25 @@ "name": "minecraft:smooth_stone", "id": -183 }, + { + "name": "minecraft:smooth_stone_slab", + "id": 44 + }, { "name": "minecraft:sniffer_egg", "id": -596 }, { "name": "minecraft:sniffer_spawn_egg", - "id": 505 + "id": 510 }, { "name": "minecraft:snort_pottery_sherd", - "id": 686 + "id": 697 }, { "name": "minecraft:snout_armor_trim_smithing_template", - "id": 697 + "id": 708 }, { "name": "minecraft:snow", @@ -4989,7 +5233,7 @@ }, { "name": "minecraft:snow_golem_spawn_egg", - "id": 511 + "id": 516 }, { "name": "minecraft:snow_layer", @@ -4997,11 +5241,11 @@ }, { "name": "minecraft:snowball", - "id": 377 + "id": 381 }, { "name": "minecraft:soul_campfire", - "id": 633 + "id": 641 }, { "name": "minecraft:soul_fire", @@ -5025,27 +5269,27 @@ }, { "name": "minecraft:sparkler", - "id": 611 + "id": 619 }, { "name": "minecraft:spawn_egg", - "id": 732 + "id": 757 }, { "name": "minecraft:spider_eye", - "id": 279 + "id": 282 }, { "name": "minecraft:spider_spawn_egg", - "id": 450 + "id": 455 }, { "name": "minecraft:spire_armor_trim_smithing_template", - "id": 699 + "id": 710 }, { "name": "minecraft:splash_potion", - "id": 572 + "id": 577 }, { "name": "minecraft:sponge", @@ -5057,7 +5301,7 @@ }, { "name": "minecraft:spruce_boat", - "id": 382 + "id": 386 }, { "name": "minecraft:spruce_button", @@ -5065,11 +5309,11 @@ }, { "name": "minecraft:spruce_chest_boat", - "id": 652 + "id": 660 }, { "name": "minecraft:spruce_door", - "id": 564 + "id": 569 }, { "name": "minecraft:spruce_double_slab", @@ -5103,9 +5347,13 @@ "name": "minecraft:spruce_pressure_plate", "id": -154 }, + { + "name": "minecraft:spruce_sapling", + "id": -825 + }, { "name": "minecraft:spruce_sign", - "id": 587 + "id": 592 }, { "name": "minecraft:spruce_slab", @@ -5133,23 +5381,23 @@ }, { "name": "minecraft:spyglass", - "id": 636 + "id": 644 }, { "name": "minecraft:squid_spawn_egg", - "id": 454 + "id": 459 }, { "name": "minecraft:stained_glass", - "id": 723 + "id": 745 }, { "name": "minecraft:stained_glass_pane", - "id": 724 + "id": 746 }, { "name": "minecraft:stained_hardened_clay", - "id": 706 + "id": 719 }, { "name": "minecraft:standing_banner", @@ -5161,7 +5409,7 @@ }, { "name": "minecraft:stick", - "id": 323 + "id": 327 }, { "name": "minecraft:sticky_piston", @@ -5177,11 +5425,11 @@ }, { "name": "minecraft:stone_axe", - "id": 318 + "id": 321 }, { "name": "minecraft:stone_block_slab", - "id": 44 + "id": 736 }, { "name": "minecraft:stone_block_slab2", @@ -5195,6 +5443,10 @@ "name": "minecraft:stone_block_slab4", "id": -166 }, + { + "name": "minecraft:stone_brick_slab", + "id": -875 + }, { "name": "minecraft:stone_brick_stairs", "id": 109 @@ -5205,11 +5457,11 @@ }, { "name": "minecraft:stone_hoe", - "id": 333 + "id": 337 }, { "name": "minecraft:stone_pickaxe", - "id": 317 + "id": 320 }, { "name": "minecraft:stone_pressure_plate", @@ -5217,7 +5469,7 @@ }, { "name": "minecraft:stone_shovel", - "id": 316 + "id": 319 }, { "name": "minecraft:stone_stairs", @@ -5225,7 +5477,7 @@ }, { "name": "minecraft:stone_sword", - "id": 315 + "id": 318 }, { "name": "minecraft:stonebrick", @@ -5241,15 +5493,15 @@ }, { "name": "minecraft:stray_spawn_egg", - "id": 466 + "id": 471 }, { "name": "minecraft:strider_spawn_egg", - "id": 500 + "id": 505 }, { "name": "minecraft:string", - "id": 329 + "id": 333 }, { "name": "minecraft:stripped_acacia_log", @@ -5345,11 +5597,15 @@ }, { "name": "minecraft:sugar", - "id": 420 + "id": 424 }, { "name": "minecraft:sugar_cane", - "id": 389 + "id": 393 + }, + { + "name": "minecraft:sunflower", + "id": 175 }, { "name": "minecraft:suspicious_gravel", @@ -5361,11 +5617,11 @@ }, { "name": "minecraft:suspicious_stew", - "id": 601 + "id": 608 }, { "name": "minecraft:sweet_berries", - "id": 288 + "id": 291 }, { "name": "minecraft:sweet_berry_bush", @@ -5373,15 +5629,19 @@ }, { "name": "minecraft:tadpole_bucket", - "id": 641 + "id": 649 }, { "name": "minecraft:tadpole_spawn_egg", - "id": 640 + "id": 648 + }, + { + "name": "minecraft:tall_grass", + "id": -864 }, { "name": "minecraft:tallgrass", - "id": 31 + "id": 741 }, { "name": "minecraft:target", @@ -5389,7 +5649,7 @@ }, { "name": "minecraft:tide_armor_trim_smithing_template", - "id": 696 + "id": 707 }, { "name": "minecraft:tinted_glass", @@ -5401,7 +5661,7 @@ }, { "name": "minecraft:tnt_minecart", - "id": 536 + "id": 541 }, { "name": "minecraft:torch", @@ -5417,15 +5677,15 @@ }, { "name": "minecraft:torchflower_seeds", - "id": 297 + "id": 300 }, { "name": "minecraft:totem_of_undying", - "id": 579 + "id": 584 }, { "name": "minecraft:trader_llama_spawn_egg", - "id": 659 + "id": 667 }, { "name": "minecraft:trapdoor", @@ -5437,7 +5697,7 @@ }, { "name": "minecraft:trial_key", - "id": 707 + "id": 259 }, { "name": "minecraft:trial_spawner", @@ -5445,7 +5705,7 @@ }, { "name": "minecraft:trident", - "id": 557 + "id": 562 }, { "name": "minecraft:trip_wire", @@ -5457,20 +5717,28 @@ }, { "name": "minecraft:tropical_fish", - "id": 267 + "id": 270 }, { "name": "minecraft:tropical_fish_bucket", - "id": 369 + "id": 373 }, { "name": "minecraft:tropical_fish_spawn_egg", - "id": 484 + "id": 489 }, { "name": "minecraft:tube_coral", "id": -131 }, + { + "name": "minecraft:tube_coral_block", + "id": -132 + }, + { + "name": "minecraft:tube_coral_fan", + "id": -133 + }, { "name": "minecraft:tuff", "id": -333 @@ -5517,15 +5785,15 @@ }, { "name": "minecraft:turtle_helmet", - "id": 584 + "id": 589 }, { "name": "minecraft:turtle_scute", - "id": 583 + "id": 588 }, { "name": "minecraft:turtle_spawn_egg", - "id": 490 + "id": 495 }, { "name": "minecraft:twisting_vines", @@ -5565,19 +5833,19 @@ }, { "name": "minecraft:vex_armor_trim_smithing_template", - "id": 695 + "id": 706 }, { "name": "minecraft:vex_spawn_egg", - "id": 481 + "id": 486 }, { "name": "minecraft:villager_spawn_egg", - "id": 453 + "id": 458 }, { "name": "minecraft:vindicator_spawn_egg", - "id": 479 + "id": 484 }, { "name": "minecraft:vine", @@ -5593,15 +5861,15 @@ }, { "name": "minecraft:wandering_trader_spawn_egg", - "id": 497 + "id": 502 }, { "name": "minecraft:ward_armor_trim_smithing_template", - "id": 693 + "id": 704 }, { "name": "minecraft:warden_spawn_egg", - "id": 643 + "id": 651 }, { "name": "minecraft:warped_button", @@ -5609,7 +5877,7 @@ }, { "name": "minecraft:warped_door", - "id": 628 + "id": 636 }, { "name": "minecraft:warped_double_slab", @@ -5629,7 +5897,7 @@ }, { "name": "minecraft:warped_fungus_on_a_stick", - "id": 629 + "id": 637 }, { "name": "minecraft:warped_hanging_sign", @@ -5657,7 +5925,7 @@ }, { "name": "minecraft:warped_sign", - "id": 626 + "id": 634 }, { "name": "minecraft:warped_slab", @@ -5693,7 +5961,7 @@ }, { "name": "minecraft:water_bucket", - "id": 365 + "id": 369 }, { "name": "minecraft:waterlily", @@ -5861,7 +6129,7 @@ }, { "name": "minecraft:wayfinder_armor_trim_smithing_template", - "id": 701 + "id": 712 }, { "name": "minecraft:weathered_chiseled_copper", @@ -5913,11 +6181,11 @@ }, { "name": "minecraft:wheat", - "id": 337 + "id": 341 }, { "name": "minecraft:wheat_seeds", - "id": 292 + "id": 295 }, { "name": "minecraft:white_candle", @@ -5941,7 +6209,7 @@ }, { "name": "minecraft:white_dye", - "id": 414 + "id": 418 }, { "name": "minecraft:white_glazed_terracotta", @@ -5963,21 +6231,25 @@ "name": "minecraft:white_terracotta", "id": 159 }, + { + "name": "minecraft:white_tulip", + "id": -835 + }, { "name": "minecraft:white_wool", "id": 35 }, { "name": "minecraft:wild_armor_trim_smithing_template", - "id": 692 + "id": 703 }, { "name": "minecraft:wind_charge", - "id": 378 + "id": 260 }, { "name": "minecraft:witch_spawn_egg", - "id": 456 + "id": 461 }, { "name": "minecraft:wither_rose", @@ -5985,27 +6257,27 @@ }, { "name": "minecraft:wither_skeleton_spawn_egg", - "id": 469 + "id": 474 }, { "name": "minecraft:wither_spawn_egg", - "id": 513 + "id": 518 }, { "name": "minecraft:wolf_armor", - "id": 710 + "id": 722 }, { "name": "minecraft:wolf_spawn_egg", - "id": 443 + "id": 448 }, { "name": "minecraft:wood", - "id": 726 + "id": 748 }, { "name": "minecraft:wooden_axe", - "id": 314 + "id": 317 }, { "name": "minecraft:wooden_button", @@ -6013,15 +6285,15 @@ }, { "name": "minecraft:wooden_door", - "id": 362 + "id": 366 }, { "name": "minecraft:wooden_hoe", - "id": 332 + "id": 336 }, { "name": "minecraft:wooden_pickaxe", - "id": 313 + "id": 316 }, { "name": "minecraft:wooden_pressure_plate", @@ -6029,27 +6301,27 @@ }, { "name": "minecraft:wooden_shovel", - "id": 312 + "id": 315 }, { "name": "minecraft:wooden_slab", - "id": 717 + "id": 735 }, { "name": "minecraft:wooden_sword", - "id": 311 + "id": 314 }, { "name": "minecraft:wool", - "id": 711 + "id": 725 }, { "name": "minecraft:writable_book", - "id": 521 + "id": 526 }, { "name": "minecraft:written_book", - "id": 522 + "id": 527 }, { "name": "minecraft:yellow_candle", @@ -6073,7 +6345,7 @@ }, { "name": "minecraft:yellow_dye", - "id": 410 + "id": 414 }, { "name": "minecraft:yellow_flower", @@ -6105,22 +6377,22 @@ }, { "name": "minecraft:zoglin_spawn_egg", - "id": 503 + "id": 508 }, { "name": "minecraft:zombie_horse_spawn_egg", - "id": 473 + "id": 478 }, { "name": "minecraft:zombie_pigman_spawn_egg", - "id": 452 + "id": 457 }, { "name": "minecraft:zombie_spawn_egg", - "id": 451 + "id": 456 }, { "name": "minecraft:zombie_villager_spawn_egg", - "id": 482 + "id": 487 } ] \ No newline at end of file diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings index 968a22bba..ec45f59c8 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 968a22bbab02d7d003c5b451a40d8bb2439b0d97 +Subproject commit ec45f59c8590945c9226921ef7e339f510983dc1 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index aa68a0bc0..8301029d2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,8 +10,7 @@ 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" -protocol = "3.0.0.Beta1-20240411.165033-129" -protocol-connection = "3.0.0.Beta1-20240411.165033-128" +protocol = "3.0.0.Beta2-20240520.153053-5" raknet = "1.0.0.CR3-20240416.144209-1" blockstateupdater="1.20.80-20240411.142413-1" mcauthlib = "e5b0bcc" @@ -117,12 +116,9 @@ viaproxy = { group = "net.raphimc", name = "ViaProxy", version.ref = "viaproxy" viaversion = { group = "com.viaversion", name = "viaversion", version.ref = "viaversion" } websocket = { group = "org.java-websocket", name = "Java-WebSocket", version.ref = "websocket" } -#protocol-common = { group = "org.cloudburstmc.protocol", name = "common", version.ref = "protocol-connection" } -#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" } -protocol-common = { group = "com.github.GeyserMC.Protocol", name = "common", version = "ade21be" } -protocol-codec = { group = "com.github.GeyserMC.Protocol", name = "bedrock-codec", version = "ade21be" } -protocol-connection = { group = "com.github.GeyserMC.Protocol", name = "bedrock-connection", version = "ade21be" } +protocol-common = { group = "org.cloudburstmc.protocol", name = "common", version.ref = "protocol" } +protocol-codec = { group = "org.cloudburstmc.protocol", name = "bedrock-codec", version.ref = "protocol" } +protocol-connection = { group = "org.cloudburstmc.protocol", name = "bedrock-connection", version.ref = "protocol" } math = { group = "org.cloudburstmc.math", name = "immutable", version = "2.0" } From cb0488a271c6db3637476477902234725461aa7f Mon Sep 17 00:00:00 2001 From: Valaphee The Meerkat <32491319+valaphee@users.noreply.github.com> Date: Mon, 27 May 2024 14:08:04 +0200 Subject: [PATCH 034/233] Fix NPE in TippedArrow when it has no components (#4694) --- .../geyser/item/type/TippedArrowItem.java | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) 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 85291886e..db33bb584 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 @@ -41,16 +41,18 @@ public class TippedArrowItem extends ArrowItem { @Override public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) { - 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); + if (components != null) { + 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): " + potionContents.getPotionId()); } - GeyserImpl.getInstance().getLogger().debug("Unknown Java potion (tipped arrow): " + potionContents.getPotionId()); } return super.translateToBedrock(count, components, mapping, mappings); } From 3570caae258e43b61bfc628d18f0408e3b08af78 Mon Sep 17 00:00:00 2001 From: Valaphee The Meerkat <32491319+valaphee@users.noreply.github.com> Date: Mon, 27 May 2024 16:53:42 +0200 Subject: [PATCH 035/233] Fix crafting output not updating sometimes (#4692) * Only cancel crafting grid future if slot == 0 * Add some comments --- .../inventory/JavaContainerSetSlotTranslator.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) 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 4372b5ea5..57da00b51 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 @@ -71,10 +71,6 @@ public class JavaContainerSetSlotTranslator extends PacketTranslator= inventory.getSize()) { GeyserLogger logger = session.getGeyser().getLogger(); @@ -111,14 +107,22 @@ public class JavaContainerSetSlotTranslator extends PacketTranslator Date: Mon, 27 May 2024 10:59:36 -0700 Subject: [PATCH 036/233] Switch to centralized GitHub actions (#4693) * Switch to centralized GitHub actions * Update PR actions as well * Publish preview only if success * Webhook on success & failure --- .github/workflows/build-remote.yml | 36 ++++----- .github/workflows/build.yml | 125 +++++++++++++---------------- .github/workflows/preview.yml | 57 +++++-------- 3 files changed, 97 insertions(+), 121 deletions(-) diff --git a/.github/workflows/build-remote.yml b/.github/workflows/build-remote.yml index d49920785..c815b4740 100644 --- a/.github/workflows/build-remote.yml +++ b/.github/workflows/build-remote.yml @@ -22,79 +22,79 @@ jobs: run: | echo "BUILD_NUMBER=${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV - - name: Set up JDK 21 + - name: Setup Java # See https://github.com/actions/setup-java/commits - uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4.0.0 + uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 with: java-version: 21 distribution: temurin - name: Checkout repository and submodules # See https://github.com/actions/checkout/commits - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 with: repository: ${{ inputs.repository }} ref: ${{ inputs.ref }} submodules: recursive - path: geyser - name: Validate Gradle Wrapper # See https://github.com/gradle/wrapper-validation-action/commits - uses: gradle/wrapper-validation-action@699bb18358f12c5b78b37bb0111d3a0e2276e0e2 # v2.1.1 + uses: gradle/actions/wrapper-validation@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + + - name: Setup Gradle + # See https://github.com/gradle/actions/commits + uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + with: + cache-read-only: true - name: Build Geyser - # 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 + run: ./gradlew build - name: Archive artifacts (Geyser Fabric) # See https://github.com/actions/upload-artifact/commits - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 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@5d5d22a31266ced268874388b861e4b58bb5c2f3 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 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@5d5d22a31266ced268874388b861e4b58bb5c2f3 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 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@5d5d22a31266ced268874388b861e4b58bb5c2f3 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 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@5d5d22a31266ced268874388b861e4b58bb5c2f3 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 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@5d5d22a31266ced268874388b861e4b58bb5c2f3 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 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@5d5d22a31266ced268874388b861e4b58bb5c2f3 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 if: success() with: name: Geyser ViaProxy diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7ec013dc2..f2f2a2c82 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,84 +21,86 @@ on: jobs: build: runs-on: ubuntu-latest - 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_RUN_NUMBER}" >> $GITHUB_ENV + - name: Get Release Info + id: release-info + uses: GeyserMC/actions/previous-release@master + with: + data: ${{ vars.RELEASEACTION_PREVRELEASE }} - name: Checkout repository and submodules # See https://github.com/actions/checkout/commits - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 with: submodules: recursive - name: Validate Gradle Wrapper - # See https://github.com/gradle/wrapper-validation-action/commits - uses: gradle/wrapper-validation-action@699bb18358f12c5b78b37bb0111d3a0e2276e0e2 # v2.1.1 + # See https://github.com/gradle/actions/commits + uses: gradle/actions/wrapper-validation@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 # See https://github.com/actions/setup-java/commits - - uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4.0.0 + - name: Setup Java + uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 with: java-version: 21 distribution: temurin - - name: Build + - name: Setup Gradle # See https://github.com/gradle/actions/commits - uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 with: - arguments: build gradle-home-cache-cleanup: true + + - name: Build Geyser + run: ./gradlew build + env: + BUILD_NUMBER: ${{ steps.release-info.outputs.curentRelease }} - name: Archive artifacts (Geyser Fabric) # See https://github.com/actions/upload-artifact/commits - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 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@5d5d22a31266ced268874388b861e4b58bb5c2f3 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 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@5d5d22a31266ced268874388b861e4b58bb5c2f3 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 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@5d5d22a31266ced268874388b861e4b58bb5c2f3 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 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@5d5d22a31266ced268874388b861e4b58bb5c2f3 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 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@5d5d22a31266ced268874388b861e4b58bb5c2f3 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 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@5d5d22a31266ced268874388b861e4b58bb5c2f3 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 if: success() with: name: Geyser ViaProxy @@ -107,17 +109,23 @@ jobs: - name: Publish to Maven Repository if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} - uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 + run: ./gradlew publish env: + BUILD_NUMBER: ${{ steps.release-info.outputs.curentRelease }} ORG_GRADLE_PROJECT_geysermcUsername: ${{ vars.DEPLOY_USER }} ORG_GRADLE_PROJECT_geysermcPassword: ${{ secrets.DEPLOY_PASS }} - with: - arguments: publish + + - name: Get Version + if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} + id: get-version + run: | + version=$(cat gradle.properties | grep -o "version=[0-9\\.]*" | cut -d"=" -f2) + echo "VERSION=${version}" >> $GITHUB_OUTPUT - name: Get Release Metadata if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} - # See https://github.com/Kas-tle/base-release-action/releases/tag/main-11 - uses: Kas-tle/base-release-action@b863fa0f89bd15267a96a72efb84aec25f168d4c # main-11 + uses: GeyserMC/actions/release@master + id: metadata with: appID: ${{ secrets.RELEASE_APP_ID }} appPrivateKey: ${{ secrets.RELEASE_APP_PK }} @@ -131,61 +139,42 @@ jobs: 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 - mv metadata.json metadata.json.tmp - version=$(cat gradle.properties | grep -o "version=[0-9\\.]*" | cut -d"=" -f2) - jq --arg project "${PROJECT}" --arg version "${version}" ' - . - | .changes |= map({"commit", "summary", "message"}) - | .downloads |= map_values({"name", "sha256"}) - | {$project, "repo", $version, "number": .build, "changes", "downloads"} - ' metadata.json.tmp > metadata.json - cat metadata.json + releaseProject: 'geyser' + releaseVersion: ${{ steps.get-version.outputs.VERSION }} - name: Publish to Downloads API if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} - 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/$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 - rsync -P -e "ssh -o StrictHostKeyChecking=no -i id_ecdsa" metadata.json $DOWNLOADS_USERNAME@$DOWNLOADS_SERVER_IP:~/uploads/$PROJECT/$GITHUB_RUN_NUMBER/ + uses: GeyserMC/actions/upload-release@master + with: + username: ${{ vars.DOWNLOADS_USERNAME }} + privateKey: ${{ secrets.DOWNLOADS_PRIVATE_KEY }} + host: ${{ secrets.DOWNLOADS_SERVER_IP }} + files: | + bootstrap/bungeecord/build/libs/Geyser-BungeeCord.jar + bootstrap/mod/fabric/build/libs/Geyser-Fabric.jar + bootstrap/mod/neoforge/build/libs/Geyser-NeoForge.jar + bootstrap/spigot/build/libs/Geyser-Spigot.jar + bootstrap/standalone/build/libs/Geyser-Standalone.jar + bootstrap/velocity/build/libs/Geyser-Velocity.jar + bootstrap/viaproxy/build/libs/Geyser-ViaProxy.jar - name: Publish to Modrinth (Fabric) - uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} env: + BUILD_NUMBER: ${{ steps.release-info.outputs.curentRelease }} MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }} - with: - arguments: fabric:modrinth - gradle-home-cache-cleanup: true + run: ./gradlew fabric:modrinth - name: Publish to Modrinth (NeoForge) - uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} env: + BUILD_NUMBER: ${{ steps.release-info.outputs.curentRelease }} MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }} - with: - arguments: neoforge:modrinth - gradle-home-cache-cleanup: true + run: ./gradlew neoforge:modrinth - name: Notify Discord if: ${{ (success() || failure()) && github.repository == 'GeyserMC/Geyser' }} - # See https://github.com/Tim203/actions-git-discord-webhook/commits - uses: Tim203/actions-git-discord-webhook@70f38ded3aca51635ec978ab4e1a58cd4cd0c2ff + uses: GeyserMC/actions/notify-discord@master with: - webhook_url: ${{ secrets.DISCORD_WEBHOOK }} + discordWebhook: ${{ secrets.DISCORD_WEBHOOK }} status: ${{ job.status }} + body: ${{ steps.metadata.outputs.body }} diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index 1268f0674..a90d60ef7 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -26,30 +26,30 @@ on: jobs: upload: runs-on: ubuntu-latest - env: - PROJECT: 'geyserpreview' steps: - 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 "VERSION=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT echo "RUN=${{ github.event.inputs.runId }}" >> $GITHUB_OUTPUT else echo "BUILD=${{ inputs.build }}" >> $GITHUB_ENV - echo "VERSION=${{ inputs.version }}" >> $GITHUB_ENV + echo "VERSION=${{ inputs.version }}" >> $GITHUB_OUTPUT echo "RUN=${{ github.run_id }}" >> $GITHUB_OUTPUT fi - - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 + - name: Download Artifacts + # See https://github.com/actions/download-artifact/commits + uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.6 with: run-id: ${{ steps.setvars.outputs.RUN }} github-token: ${{ secrets.GITHUB_TOKEN }} merge-multiple: true - name: Get Preview Metadata if: success() - # See https://github.com/Kas-tle/base-release-action/releases/tag/main-11 - uses: Kas-tle/base-release-action@664c39985eb9d0d393ce98e7eb8414d3d98e762a # main-11 + uses: GeyserMC/actions/release@master + id: metadata with: appID: ${{ secrets.RELEASE_APP_ID }} appPrivateKey: ${{ secrets.RELEASE_APP_PK }} @@ -64,33 +64,20 @@ jobs: releaseEnabled: false saveMetadata: true updateReleaseData: false - - name: Update Generated Metadata - if: success() - run: | - cat metadata.json - echo - 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"} - ' metadata.json.tmp > metadata.json - cat metadata.json + releaseProject: 'geyserpreview' + releaseVersion: ${{ steps.setvars.outputs.VERSION }} - 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/ + uses: GeyserMC/actions/upload-release@master + with: + username: ${{ vars.DOWNLOADS_USERNAME }} + privateKey: ${{ secrets.DOWNLOADS_PRIVATE_KEY }} + host: ${{ secrets.DOWNLOADS_SERVER_IP }} + files: | + Geyser-BungeeCord.jar + Geyser-Fabric.jar + Geyser-NeoForge.jar + Geyser-Spigot.jar + Geyser-Standalone.jar + Geyser-Velocity.jar + Geyser-ViaProxy.jar From 444b5ecee8bf80e8ae93caa52dad8918a29a7542 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Mon, 27 May 2024 14:33:11 -0400 Subject: [PATCH 037/233] Remove BlockStateUpdater dependency Not currently used --- core/build.gradle.kts | 1 - .../populator/BlockRegistryPopulator.java | 15 --------------- gradle/libs.versions.toml | 3 --- 3 files changed, 19 deletions(-) diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 42d4e13c5..a27c4fc89 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -24,7 +24,6 @@ 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/registry/populator/BlockRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java index 936935306..6b856c509 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 @@ -35,8 +35,6 @@ 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.cloudburstmc.blockstateupdater.BlockStateUpdater; -import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; import org.cloudburstmc.nbt.*; import org.cloudburstmc.protocol.bedrock.codec.v671.Bedrock_v671; import org.cloudburstmc.protocol.bedrock.codec.v685.Bedrock_v685; @@ -85,19 +83,6 @@ public final class BlockRegistryPopulator { 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) { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8301029d2..1995a6ada 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,7 +12,6 @@ gson = "2.3.1" # Provided by Spigot 1.8.8 websocket = "1.5.1" protocol = "3.0.0.Beta2-20240520.153053-5" raknet = "1.0.0.CR3-20240416.144209-1" -blockstateupdater="1.20.80-20240411.142413-1" mcauthlib = "e5b0bcc" mcprotocollib = "1.20.6-2-20240520.030045-8" adventure = "4.14.0" @@ -122,8 +121,6 @@ protocol-connection = { group = "org.cloudburstmc.protocol", name = "bedrock-con 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" } From 675faf6bb45676e248bb1f0b0f871429966e8feb Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Mon, 27 May 2024 14:35:02 -0400 Subject: [PATCH 038/233] Remove unused chat class --- .../geysermc/geyser/text/ChatTypeEntry.java | 53 ------------------- 1 file changed, 53 deletions(-) delete mode 100644 core/src/main/java/org/geysermc/geyser/text/ChatTypeEntry.java diff --git a/core/src/main/java/org/geysermc/geyser/text/ChatTypeEntry.java b/core/src/main/java/org/geysermc/geyser/text/ChatTypeEntry.java deleted file mode 100644 index f139b0bba..000000000 --- a/core/src/main/java/org/geysermc/geyser/text/ChatTypeEntry.java +++ /dev/null @@ -1,53 +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.text; - -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 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); - private static final ChatTypeEntry RAW = new ChatTypeEntry(TextPacket.Type.RAW, null); - - /** - * Apply defaults to a map so it isn't empty in the event a chat message is sent before the login packet. - */ - public static void applyDefaults(Int2ObjectMap chatTypes) { - // So the proper way to do this, probably, would be to dump the NBT data from vanilla and load it. - // But, the only way this happens is if a chat message is sent to us before the login packet, which is rare. - // So we'll just make sure chat ends up in the right place. - chatTypes.put(BuiltinChatType.CHAT.ordinal(), CHAT); - chatTypes.put(BuiltinChatType.SAY_COMMAND.ordinal(), RAW); - chatTypes.put(BuiltinChatType.MSG_COMMAND_INCOMING.ordinal(), RAW); - chatTypes.put(BuiltinChatType.MSG_COMMAND_OUTGOING.ordinal(), RAW); - chatTypes.put(BuiltinChatType.TEAM_MSG_COMMAND_INCOMING.ordinal(), RAW); - chatTypes.put(BuiltinChatType.TEAM_MSG_COMMAND_OUTGOING.ordinal(), RAW); - chatTypes.put(BuiltinChatType.EMOTE_COMMAND.ordinal(), RAW); - } -} From fe63665d8818af2836e9db3447f8625d49beaeb6 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Tue, 28 May 2024 00:11:05 -0700 Subject: [PATCH 039/233] Composite gradle setup and artifact archival (#4696) * Composite gradle setup and artifact archival * Remove 'geyser' path for PRs * Move upload-preview workflow --- .github/workflows/build-remote.yml | 85 +++++-------------------- .github/workflows/build.yml | 86 +++++--------------------- .github/workflows/dispatch-preview.yml | 33 ++++++++++ .github/workflows/preview.yml | 83 ------------------------- .github/workflows/pull-request.yml | 16 ++++- 5 files changed, 77 insertions(+), 226 deletions(-) create mode 100644 .github/workflows/dispatch-preview.yml delete mode 100644 .github/workflows/preview.yml diff --git a/.github/workflows/build-remote.yml b/.github/workflows/build-remote.yml index c815b4740..7cb89cc61 100644 --- a/.github/workflows/build-remote.yml +++ b/.github/workflows/build-remote.yml @@ -22,81 +22,26 @@ jobs: run: | echo "BUILD_NUMBER=${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV - - name: Setup Java - # See https://github.com/actions/setup-java/commits - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 - with: - java-version: 21 - distribution: temurin - - - name: Checkout repository and submodules - # See https://github.com/actions/checkout/commits - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - with: - repository: ${{ inputs.repository }} - ref: ${{ inputs.ref }} - submodules: recursive - - - name: Validate Gradle Wrapper - # See https://github.com/gradle/wrapper-validation-action/commits - uses: gradle/actions/wrapper-validation@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 - - name: Setup Gradle - # See https://github.com/gradle/actions/commits - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: GeyserMC/actions/setup-gradle-composite@master with: - cache-read-only: true + checkout_repository: ${{ inputs.repository }} + checkout_ref: ${{ inputs.ref }} + setup-java_java-version: 21 + setup-gradle_cache-read-only: true - name: Build Geyser run: ./gradlew build - - name: Archive artifacts (Geyser Fabric) - # See https://github.com/actions/upload-artifact/commits - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + - name: Archive Artifacts + uses: GeyserMC/actions/upload-multi-artifact@master 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@65462800fd760344b1a7b4382951275a0abb4808 - 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@65462800fd760344b1a7b4382951275a0abb4808 - 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@65462800fd760344b1a7b4382951275a0abb4808 - 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@65462800fd760344b1a7b4382951275a0abb4808 - 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@65462800fd760344b1a7b4382951275a0abb4808 - 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@65462800fd760344b1a7b4382951275a0abb4808 - if: success() - with: - name: Geyser ViaProxy - path: geyser/bootstrap/viaproxy/build/libs/Geyser-ViaProxy.jar - if-no-files-found: error \ No newline at end of file + artifacts: | + bootstrap/mod/fabric/build/libs/Geyser-Fabric.jar + bootstrap/mod/neoforge/build/libs/Geyser-NeoForge.jar + bootstrap/standalone/build/libs/Geyser-Standalone.jar + bootstrap/spigot/build/libs/Geyser-Spigot.jar + bootstrap/bungeecord/build/libs/Geyser-BungeeCord.jar + bootstrap/velocity/build/libs/Geyser-Velocity.jar + bootstrap/viaproxy/build/libs/Geyser-ViaProxy.jar \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f2f2a2c82..b8f855a53 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,84 +28,28 @@ jobs: with: data: ${{ vars.RELEASEACTION_PREVRELEASE }} - - name: Checkout repository and submodules - # See https://github.com/actions/checkout/commits - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - with: - submodules: recursive - - - name: Validate Gradle Wrapper - # See https://github.com/gradle/actions/commits - uses: gradle/actions/wrapper-validation@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 - - # See https://github.com/actions/setup-java/commits - - name: Setup Java - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 - with: - java-version: 21 - distribution: temurin - - name: Setup Gradle - # See https://github.com/gradle/actions/commits - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: GeyserMC/actions/setup-gradle-composite@master with: - gradle-home-cache-cleanup: true + setup-java_java-version: 21 - name: Build Geyser run: ./gradlew build env: BUILD_NUMBER: ${{ steps.release-info.outputs.curentRelease }} - - name: Archive artifacts (Geyser Fabric) - # See https://github.com/actions/upload-artifact/commits - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + - name: Archive Artifacts + uses: GeyserMC/actions/upload-multi-artifact@master 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@65462800fd760344b1a7b4382951275a0abb4808 - 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@65462800fd760344b1a7b4382951275a0abb4808 - 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@65462800fd760344b1a7b4382951275a0abb4808 - 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@65462800fd760344b1a7b4382951275a0abb4808 - 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@65462800fd760344b1a7b4382951275a0abb4808 - 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@65462800fd760344b1a7b4382951275a0abb4808 - if: success() - with: - name: Geyser ViaProxy - path: bootstrap/viaproxy/build/libs/Geyser-ViaProxy.jar - if-no-files-found: error + artifacts: | + bootstrap/mod/fabric/build/libs/Geyser-Fabric.jar + bootstrap/mod/neoforge/build/libs/Geyser-NeoForge.jar + bootstrap/standalone/build/libs/Geyser-Standalone.jar + bootstrap/spigot/build/libs/Geyser-Spigot.jar + bootstrap/bungeecord/build/libs/Geyser-BungeeCord.jar + bootstrap/velocity/build/libs/Geyser-Velocity.jar + bootstrap/viaproxy/build/libs/Geyser-ViaProxy.jar - name: Publish to Maven Repository if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} @@ -116,14 +60,14 @@ jobs: ORG_GRADLE_PROJECT_geysermcPassword: ${{ secrets.DEPLOY_PASS }} - name: Get Version - if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} + if: ${{ (success() || failure()) && github.repository == 'GeyserMC/Geyser' }} id: get-version run: | version=$(cat gradle.properties | grep -o "version=[0-9\\.]*" | cut -d"=" -f2) echo "VERSION=${version}" >> $GITHUB_OUTPUT - name: Get Release Metadata - if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} + if: ${{ (success() || failure()) && github.repository == 'GeyserMC/Geyser' }} uses: GeyserMC/actions/release@master id: metadata with: @@ -141,6 +85,7 @@ jobs: saveMetadata: true releaseProject: 'geyser' releaseVersion: ${{ steps.get-version.outputs.VERSION }} + - name: Publish to Downloads API if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} uses: GeyserMC/actions/upload-release@master @@ -156,6 +101,7 @@ jobs: bootstrap/standalone/build/libs/Geyser-Standalone.jar bootstrap/velocity/build/libs/Geyser-Velocity.jar bootstrap/viaproxy/build/libs/Geyser-ViaProxy.jar + changelog: ${{ steps.metadata.outputs.body }} - name: Publish to Modrinth (Fabric) if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} diff --git a/.github/workflows/dispatch-preview.yml b/.github/workflows/dispatch-preview.yml new file mode 100644 index 000000000..83df08e37 --- /dev/null +++ b/.github/workflows/dispatch-preview.yml @@ -0,0 +1,33 @@ +name: Dispatch 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: + dispatch-preview: + # Allow access to secrets if we are uploading a preview + secrets: inherit + uses: GeyserMC/actions/.github/workflows/upload-preview.yml@master + with: + build: ${{ inputs.build }} + version: ${{ inputs.version }} + 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 + project: geyserpreview + runId: ${{ inputs.runId }} \ No newline at end of file diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml deleted file mode 100644 index a90d60ef7..000000000 --- a/.github/workflows/preview.yml +++ /dev/null @@ -1,83 +0,0 @@ -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' - 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 - steps: - - 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_OUTPUT - echo "RUN=${{ github.event.inputs.runId }}" >> $GITHUB_OUTPUT - else - echo "BUILD=${{ inputs.build }}" >> $GITHUB_ENV - echo "VERSION=${{ inputs.version }}" >> $GITHUB_OUTPUT - echo "RUN=${{ github.run_id }}" >> $GITHUB_OUTPUT - fi - - name: Download Artifacts - # See https://github.com/actions/download-artifact/commits - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.6 - with: - run-id: ${{ steps.setvars.outputs.RUN }} - github-token: ${{ secrets.GITHUB_TOKEN }} - merge-multiple: true - - name: Get Preview Metadata - if: success() - uses: GeyserMC/actions/release@master - id: metadata - 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 - releaseProject: 'geyserpreview' - releaseVersion: ${{ steps.setvars.outputs.VERSION }} - - name: Publish to Downloads API - if: success() - uses: GeyserMC/actions/upload-release@master - with: - username: ${{ vars.DOWNLOADS_USERNAME }} - privateKey: ${{ secrets.DOWNLOADS_PRIVATE_KEY }} - host: ${{ secrets.DOWNLOADS_SERVER_IP }} - files: | - Geyser-BungeeCord.jar - Geyser-Fabric.jar - Geyser-NeoForge.jar - Geyser-Spigot.jar - Geyser-Standalone.jar - Geyser-Velocity.jar - Geyser-ViaProxy.jar diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index bc5e57b6b..6167bb18e 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -8,7 +8,7 @@ jobs: # Forbid access to secrets nor GH Token perms while building the PR permissions: {} secrets: {} - uses: ./.github/workflows/build-remote.yml + uses: GeyserMC/Geyser/.github/workflows/build-remote.yml@master with: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.event.pull_request.head.sha }} @@ -18,7 +18,17 @@ jobs: 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 + uses: GeyserMC/actions/.github/workflows/upload-preview.yml@master with: build: ${{ github.run_number }} - version: pr.${{ github.event.pull_request.number }} \ No newline at end of file + version: pr.${{ github.event.pull_request.number }} + 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 + project: geyserpreview + runId: ${{ github.run_id }} \ No newline at end of file From 0fcf0f9b4f62e4b0deb03678f029f60b2112ae8b Mon Sep 17 00:00:00 2001 From: chris Date: Tue, 28 May 2024 17:23:19 +0200 Subject: [PATCH 040/233] Update Bungee version check, create logger earlier (#4697) * use the logger where possible instead of system.out.print * make loggers final * yeet unused constructors * velocity is more complicated --- .../bungeecord/GeyserBungeeLogger.java | 7 +-- .../bungeecord/GeyserBungeePlugin.java | 23 +++++----- .../platform/mod/GeyserModBootstrap.java | 7 ++- .../geyser/platform/mod/GeyserModLogger.java | 4 -- .../platform/spigot/GeyserPaperLogger.java | 4 +- .../platform/spigot/GeyserSpigotLogger.java | 4 +- .../platform/spigot/GeyserSpigotPlugin.java | 43 +++++++++---------- .../standalone/GeyserStandaloneBootstrap.java | 4 +- .../velocity/GeyserVelocityLogger.java | 4 +- .../velocity/GeyserVelocityPlugin.java | 38 ++++++++-------- .../java/org/geysermc/geyser/GeyserImpl.java | 1 + .../geysermc/geyser/text/GeyserLocale.java | 11 ++--- 12 files changed, 67 insertions(+), 83 deletions(-) diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeLogger.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeLogger.java index daeb20102..e8cf7ee39 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeLogger.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeLogger.java @@ -26,22 +26,19 @@ package org.geysermc.geyser.platform.bungeecord; import lombok.Getter; +import lombok.RequiredArgsConstructor; import lombok.Setter; import org.geysermc.geyser.GeyserLogger; import java.util.logging.Level; import java.util.logging.Logger; +@RequiredArgsConstructor public class GeyserBungeeLogger implements GeyserLogger { private final Logger logger; @Getter @Setter private boolean debug; - public GeyserBungeeLogger(Logger logger, boolean debug) { - this.logger = logger; - this.debug = debug; - } - @Override public void severe(String message) { logger.severe(message); 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 4191c8578..062ef6f76 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 @@ -58,14 +58,13 @@ import java.util.Map; import java.util.Optional; import java.util.UUID; import java.util.concurrent.TimeUnit; -import java.util.logging.Level; public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { private GeyserCommandManager geyserCommandManager; private GeyserBungeeConfiguration geyserConfig; private GeyserBungeeInjector geyserInjector; - private GeyserBungeeLogger geyserLogger; + private final GeyserBungeeLogger geyserLogger = new GeyserBungeeLogger(getLogger()); private IGeyserPingPassthrough geyserBungeePingPassthrough; private GeyserImpl geyser; @@ -82,21 +81,21 @@ 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_3"); + ProtocolConstants.class.getField("MINECRAFT_1_20_5"); } catch (NoSuchFieldException e) { - getLogger().warning(" / \\"); - getLogger().warning(" / \\"); - getLogger().warning(" / | \\"); - getLogger().warning(" / | \\ " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_proxy", getProxy().getName())); - getLogger().warning(" / \\ " + GeyserLocale.getLocaleStringLog("geyser.may_not_work_as_intended_all_caps")); - getLogger().warning(" / o \\"); - getLogger().warning("/_____________\\"); + geyserLogger.error(" / \\"); + geyserLogger.error(" / \\"); + geyserLogger.error(" / | \\"); + geyserLogger.error(" / | \\ " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_proxy", getProxy().getName())); + geyserLogger.error(" / \\ " + GeyserLocale.getLocaleStringLog("geyser.may_not_work_as_intended_all_caps")); + geyserLogger.error(" / o \\"); + geyserLogger.error("/_____________\\"); } if (!this.loadConfig()) { return; } - this.geyserLogger = new GeyserBungeeLogger(getLogger(), geyserConfig.isDebugMode()); + this.geyserLogger.setDebug(geyserConfig.isDebugMode()); GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); this.geyser = GeyserImpl.load(PlatformType.BUNGEECORD, this); this.geyserInjector = new GeyserBungeeInjector(this); @@ -293,7 +292,7 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { "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); + geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex); ex.printStackTrace(); return false; } 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 786faac93..d7373f0a9 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 @@ -34,7 +34,6 @@ 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; import org.geysermc.geyser.GeyserBootstrap; @@ -80,7 +79,7 @@ public abstract class GeyserModBootstrap implements GeyserBootstrap { private GeyserCommandManager geyserCommandManager; private GeyserModConfiguration geyserConfig; private GeyserModInjector geyserInjector; - private GeyserModLogger geyserLogger; + private final GeyserModLogger geyserLogger = new GeyserModLogger(); private IGeyserPingPassthrough geyserPingPassthrough; private WorldManager geyserWorldManager; @@ -92,7 +91,7 @@ public abstract class GeyserModBootstrap implements GeyserBootstrap { if (!loadConfig()) { return; } - this.geyserLogger = new GeyserModLogger(geyserConfig.isDebugMode()); + this.geyserLogger.setDebug(geyserConfig.isDebugMode()); GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); this.geyser = GeyserImpl.load(this.platform.platformType(), this); @@ -288,7 +287,7 @@ public abstract class GeyserModBootstrap implements GeyserBootstrap { this.geyserConfig = FileUtils.loadConfig(configFile, GeyserModConfiguration.class); return true; } catch (IOException ex) { - LogManager.getLogger("geyser").error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex); + geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex); ex.printStackTrace(); return false; } diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModLogger.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModLogger.java index 444b725e9..9260288d7 100644 --- a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModLogger.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModLogger.java @@ -37,10 +37,6 @@ public class GeyserModLogger implements GeyserLogger { private boolean debug; - public GeyserModLogger(boolean isDebug) { - debug = isDebug; - } - @Override public void severe(String message) { logger.fatal(message); diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperLogger.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperLogger.java index 930f84cec..9ebd6519a 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperLogger.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserPaperLogger.java @@ -34,8 +34,8 @@ import java.util.logging.Logger; public final class GeyserPaperLogger extends GeyserSpigotLogger { private final ComponentLogger componentLogger; - public GeyserPaperLogger(Plugin plugin, Logger logger, boolean debug) { - super(logger, debug); + public GeyserPaperLogger(Plugin plugin, Logger logger) { + super(logger); componentLogger = plugin.getComponentLogger(); } diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotLogger.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotLogger.java index fe56cba1c..5c6101eae 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotLogger.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotLogger.java @@ -25,15 +25,15 @@ package org.geysermc.geyser.platform.spigot; -import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.RequiredArgsConstructor; import lombok.Setter; import org.geysermc.geyser.GeyserLogger; import java.util.logging.Level; import java.util.logging.Logger; -@AllArgsConstructor +@RequiredArgsConstructor public class GeyserSpigotLogger implements GeyserLogger { private final Logger logger; @Getter @Setter 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 e33de5f9b..d138ad074 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 @@ -79,14 +79,14 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.UUID; -import java.util.logging.Level; public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { private GeyserSpigotCommandManager geyserCommandManager; private GeyserSpigotConfiguration geyserConfig; private GeyserSpigotInjector geyserInjector; - private GeyserSpigotLogger geyserLogger; + private final GeyserSpigotLogger geyserLogger = GeyserPaperLogger.supported() ? + new GeyserPaperLogger(this, getLogger()) : new GeyserSpigotLogger(getLogger()); private IGeyserPingPassthrough geyserSpigotPingPassthrough; private GeyserSpigotWorldManager geyserWorldManager; @@ -114,12 +114,12 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { // We depend on this as a fallback in certain scenarios BlockData.class.getMethod("getAsString"); } catch (ClassNotFoundException | NoSuchMethodException e) { - getLogger().severe("*********************************************"); - getLogger().severe(""); - getLogger().severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server.header")); - getLogger().severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server.message", "1.13.2")); - getLogger().severe(""); - getLogger().severe("*********************************************"); + geyserLogger.error("*********************************************"); + geyserLogger.error(""); + geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server.header")); + geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server.message", "1.13.2")); + geyserLogger.error(""); + geyserLogger.error("*********************************************"); Bukkit.getPluginManager().disablePlugin(this); return; } @@ -128,12 +128,12 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { Class.forName("net.md_5.bungee.chat.ComponentSerializer"); } catch (ClassNotFoundException e) { if (!PaperAdventure.canSendMessageUsingComponent()) { // Prepare for Paper eventually removing Bungee chat - getLogger().severe("*********************************************"); - getLogger().severe(""); - getLogger().severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server_type.header", getServer().getName())); - getLogger().severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server_type.message", "Paper")); - getLogger().severe(""); - getLogger().severe("*********************************************"); + geyserLogger.error("*********************************************"); + geyserLogger.error(""); + geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server_type.header", getServer().getName())); + geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server_type.message", "Paper")); + geyserLogger.error(""); + geyserLogger.error("*********************************************"); Bukkit.getPluginManager().disablePlugin(this); return; } @@ -142,11 +142,11 @@ 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("*********************************************"); + geyserLogger.error("*********************************************"); + geyserLogger.error(""); + geyserLogger.error("This version of Spigot is using an outdated version of netty. Please use Paper instead!"); + geyserLogger.error(""); + geyserLogger.error("*********************************************"); Bukkit.getPluginManager().disablePlugin(this); return; } @@ -154,8 +154,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { if (!loadConfig()) { return; } - this.geyserLogger = GeyserPaperLogger.supported() ? new GeyserPaperLogger(this, getLogger(), geyserConfig.isDebugMode()) - : new GeyserSpigotLogger(getLogger(), geyserConfig.isDebugMode()); + this.geyserLogger.setDebug(geyserConfig.isDebugMode()); GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); // Turn "(MC: 1.16.4)" into 1.16.4. @@ -486,7 +485,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { (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); + geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex); ex.printStackTrace(); Bukkit.getPluginManager().disablePlugin(this); return false; 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 039004867..f289fa2ba 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 @@ -71,7 +71,7 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap { private GeyserCommandManager geyserCommandManager; private GeyserStandaloneConfiguration geyserConfig; - private GeyserStandaloneLogger geyserLogger; + private final GeyserStandaloneLogger geyserLogger = new GeyserStandaloneLogger(); private IGeyserPingPassthrough geyserPingPassthrough; private GeyserStandaloneGUI gui; @Getter @@ -181,8 +181,6 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap { } } - this.geyserLogger = new GeyserStandaloneLogger(); - if (useGui && gui == null) { gui = new GeyserStandaloneGUI(geyserLogger); gui.redirectSystemStreams(); diff --git a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityLogger.java b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityLogger.java index 567870e7f..4d10e4daf 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityLogger.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityLogger.java @@ -25,13 +25,13 @@ package org.geysermc.geyser.platform.velocity; -import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.RequiredArgsConstructor; import lombok.Setter; import org.geysermc.geyser.GeyserLogger; import org.slf4j.Logger; -@AllArgsConstructor +@RequiredArgsConstructor public class GeyserVelocityLogger implements GeyserLogger { private final Logger logger; @Getter @Setter 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 347a47d63..539bdadbf 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,44 +64,44 @@ 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 { - @Inject - private Logger logger; - - @Inject - private ProxyServer proxyServer; - - @Inject - private CommandManager commandManager; + private final ProxyServer proxyServer; + private final CommandManager commandManager; + private final GeyserVelocityLogger geyserLogger; private GeyserCommandManager geyserCommandManager; private GeyserVelocityConfiguration geyserConfig; private GeyserVelocityInjector geyserInjector; - private GeyserVelocityLogger geyserLogger; private IGeyserPingPassthrough geyserPingPassthrough; - private GeyserImpl geyser; @Getter private final Path configFolder = Paths.get("plugins/" + GeyserImpl.NAME + "-Velocity/"); + @Inject + public GeyserVelocityPlugin(ProxyServer server, Logger logger, CommandManager manager) { + this.geyserLogger = new GeyserVelocityLogger(logger); + this.proxyServer = server; + this.commandManager = manager; + } + @Override public void onGeyserInitialize() { GeyserLocale.init(this); 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("/_____________\\"); + geyserLogger.error(" / \\"); + geyserLogger.error(" / \\"); + geyserLogger.error(" / | \\"); + geyserLogger.error(" / | \\ " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_proxy", proxyServer.getVersion().getName())); + geyserLogger.error(" / \\ " + GeyserLocale.getLocaleStringLog("geyser.may_not_work_as_intended_all_caps")); + geyserLogger.error(" / o \\"); + geyserLogger.error("/_____________\\"); } if (!loadConfig()) { return; } - this.geyserLogger = new GeyserVelocityLogger(logger, geyserConfig.isDebugMode()); + this.geyserLogger.setDebug(geyserConfig.isDebugMode()); GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); this.geyser = GeyserImpl.load(PlatformType.VELOCITY, this); @@ -249,7 +249,7 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { "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); + geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex); ex.printStackTrace(); return false; } diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index d5635acf9..6a404ae11 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -766,6 +766,7 @@ public class GeyserImpl implements GeyserApi { return 0; } + //noinspection DataFlowIssue return Integer.parseInt(BUILD_NUMBER); } 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 c6a58e75e..cfe950409 100644 --- a/core/src/main/java/org/geysermc/geyser/text/GeyserLocale.java +++ b/core/src/main/java/org/geysermc/geyser/text/GeyserLocale.java @@ -148,9 +148,9 @@ public class GeyserLocale { } catch (IOException ignored) {} } } else { - if (GeyserImpl.getInstance() != null && !validLocalLanguage) { + if (!validLocalLanguage) { // Don't warn on missing locales if a local file has been found - GeyserImpl.getInstance().getLogger().warning("Missing locale: " + locale); + bootstrap.getGeyserLogger().warning("Missing locale: " + locale); } } @@ -162,12 +162,7 @@ public class GeyserLocale { localeProp.load(stream); } catch (IOException e) { String message = "Unable to load custom language override!"; - if (GeyserImpl.getInstance() != null) { - GeyserImpl.getInstance().getLogger().error(message, e); - } else { - System.err.println(message); - e.printStackTrace(); - } + bootstrap.getGeyserLogger().error(message, e); } LOCALE_MAPPINGS.putIfAbsent(locale, localeProp); From 63c84bc25bacc6df0384dcd2542fe1103358f096 Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 29 May 2024 06:39:39 +0200 Subject: [PATCH 041/233] Yeet lectern cache (#4695) * attempt to yeet lectern cache * yeet lecternutils usage * properly update lecterns * yeet accidental diff --- .../mod/world/GeyserModWorldManager.java | 106 +----------------- .../manager/GeyserSpigotWorldManager.java | 72 ------------ .../geyser/level/GeyserWorldManager.java | 56 +-------- .../geysermc/geyser/level/WorldManager.java | 36 ------ .../geyser/level/block/type/Block.java | 65 +++++------ .../geyser/level/block/type/BlockState.java | 9 ++ .../geyser/level/block/type/LecternBlock.java | 66 ++++++++--- .../geyser/session/GeyserSession.java | 15 --- .../inventory/LecternInventoryTranslator.java | 35 +++--- .../level/JavaForgetLevelChunkTranslator.java | 12 -- .../JavaLevelChunkWithLightTranslator.java | 24 +--- .../geysermc/geyser/util/DimensionUtils.java | 3 - .../geysermc/geyser/util/InventoryUtils.java | 1 - 13 files changed, 108 insertions(+), 392 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 656305690..7aac684bb 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,6 @@ package org.geysermc.geyser.platform.mod.world; -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; @@ -48,24 +43,19 @@ 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; -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; -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; +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 java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.concurrent.CompletableFuture; @@ -121,94 +111,6 @@ public class GeyserModWorldManager extends GeyserWorldManager { return SharedConstants.getCurrentVersion().getProtocolVersion() == GameProtocol.getJavaProtocolVersion(); } - @Override - public boolean shouldExpectLecternHandled(GeyserSession session) { - return true; - } - - @Override - public void sendLecternData(GeyserSession session, int x, int z, List blockEntityInfos) { - server.execute(() -> { - ServerPlayer player = getPlayer(session); - if (player == null) { - 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(), - blockEntityInfo.getY(), chunkBlockZ + blockEntityInfo.getZ())); - sendLecternData(session, blockEntity, true); - } - }); - } - - @Override - public void sendLecternData(GeyserSession session, int x, int y, int z) { - server.execute(() -> { - ServerPlayer player = getPlayer(session); - 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); - }); - } - - private void sendLecternData(GeyserSession session, BlockEntity blockEntity, boolean isChunkLoad) { - if (!(blockEntity instanceof LecternBlockEntity lectern)) { - return; - } - - int x = blockEntity.getBlockPos().getX(); - int y = blockEntity.getBlockPos().getY(); - int z = blockEntity.getBlockPos().getZ(); - - if (!lectern.hasBook()) { - if (!isChunkLoad) { - BlockEntityUtils.updateBlockEntity(session, LecternUtils.getBaseLecternTag(x, y, z, 0).build(), Vector3i.from(x, y, z)); - } - return; - } - - ItemStack book = lectern.getBook(); - int pageCount = getPageCount(book); - boolean hasBookPages = pageCount > 0; - NbtMapBuilder lecternTag = LecternUtils.getBaseLecternTag(x, y, z, hasBookPages ? pageCount : 1); - lecternTag.putInt("page", lectern.getPage() / 2); - NbtMapBuilder bookTag = NbtMap.builder() - .putByte("Count", (byte) book.getCount()) - .putShort("Damage", (short) 0) - .putString("Name", "minecraft:writable_book"); - List pages = new ArrayList<>(hasBookPages ? pageCount : 1); - if (hasBookPages) { - List bookPages = getPages(book); - for (String page : bookPages) { - NbtMapBuilder pageBuilder = NbtMap.builder() - .putString("photoname", "") - .putString("text", page); - pages.add(pageBuilder.build()); - } - } else { - // Empty page - NbtMapBuilder pageBuilder = NbtMap.builder() - .putString("photoname", "") - .putString("text", ""); - pages.add(pageBuilder.build()); - } - - bookTag.putCompound("tag", NbtMap.builder().putList("pages", NbtType.COMPOUND, pages).build()); - lecternTag.putCompound("book", bookTag.build()); - NbtMap blockEntityTag = lecternTag.build(); - BlockEntityUtils.updateBlockEntity(session, blockEntityTag, Vector3i.from(x, y, z)); - } - @Override public boolean hasPermission(GeyserSession session, String permission) { ServerPlayer player = getPlayer(session); 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 f45b68675..e247a72c7 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 @@ -27,16 +27,12 @@ package org.geysermc.geyser.platform.spigot.world.manager; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import org.bukkit.Bukkit; -import org.bukkit.Chunk; 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; @@ -44,12 +40,9 @@ import org.geysermc.geyser.level.GameRule; import org.geysermc.geyser.level.WorldManager; import org.geysermc.geyser.registry.BlockRegistries; 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.Objects; import java.util.concurrent.CompletableFuture; @@ -58,11 +51,9 @@ import java.util.concurrent.CompletableFuture; */ public class GeyserSpigotWorldManager extends WorldManager { private final Plugin plugin; - private final BukkitLecterns lecterns; public GeyserSpigotWorldManager(Plugin plugin) { this.plugin = plugin; - this.lecterns = new BukkitLecterns(plugin); } @Override @@ -95,69 +86,6 @@ public class GeyserSpigotWorldManager extends WorldManager { return true; } - @Override - public void sendLecternData(GeyserSession session, int x, int y, int z) { - Player bukkitPlayer; - if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUsername())) == null) { - return; - } - - Block block = bukkitPlayer.getWorld().getBlockAt(x, y, z); - // Run as a task to prevent async issues - SchedulerUtils.runTask(this.plugin, () -> sendLecternData(session, block, false), block); - } - - public void sendLecternData(GeyserSession session, int x, int z, List blockEntityInfos) { - Player bukkitPlayer; - if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUsername())) == null) { - return; - } - if (SchedulerUtils.FOLIA) { - Chunk chunk = getChunk(bukkitPlayer.getWorld(), x, z); - if (chunk == null) { - return; - } - Bukkit.getRegionScheduler().execute(this.plugin, bukkitPlayer.getWorld(), x, z, () -> - sendLecternData(session, chunk, blockEntityInfos)); - } else { - Bukkit.getScheduler().runTask(this.plugin, () -> { - Chunk chunk = getChunk(bukkitPlayer.getWorld(), x, z); - if (chunk == null) { - return; - } - sendLecternData(session, chunk, blockEntityInfos); - }); - } - } - - private @Nullable Chunk getChunk(World world, int x, int z) { - if (!world.isChunkLoaded(x, z)) { - return null; - } - return world.getChunkAt(x, z); - } - - 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()); - sendLecternData(session, block, true); - } - } - - private void sendLecternData(GeyserSession session, Block block, boolean isChunkLoad) { - NbtMap blockEntityTag = this.lecterns.getLecternData(block, isChunkLoad); - if (blockEntityTag != null) { - BlockEntityUtils.updateBlockEntity(session, blockEntityTag, BukkitUtils.getVector(block.getLocation())); - } - } - - @Override - public boolean shouldExpectLecternHandled(GeyserSession session) { - return true; - } - public boolean getGameRuleBool(GeyserSession session, GameRule gameRule) { org.bukkit.GameRule bukkitGameRule = org.bukkit.GameRule.getByName(gameRule.getJavaID()); if (bukkitGameRule == null) { 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 3144f0cb2..9faa7424c 100644 --- a/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java +++ b/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java @@ -28,22 +28,17 @@ package org.geysermc.geyser.level; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; 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; -import org.geysermc.erosion.packet.backendbound.*; +import org.geysermc.erosion.packet.backendbound.BackendboundBatchBlockRequestPacket; +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; -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; public class GeyserWorldManager extends WorldManager { @@ -92,51 +87,6 @@ public class GeyserWorldManager extends WorldManager { return false; } - @Override - public void sendLecternData(GeyserSession session, int x, int z, List blockEntityInfos) { - var erosionHandler = session.getErosionHandler().getAsActive(); - if (erosionHandler == null) { - // No-op - don't send any additional information other than what the chunk has already sent - 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())); - } - erosionHandler.sendPacket(new BackendboundBatchBlockEntityPacket(x, z, vectors)); - } - - @Override - public void sendLecternData(GeyserSession session, int x, int y, int z) { - var erosionHandler = session.getErosionHandler().getAsActive(); - if (erosionHandler != null) { - erosionHandler.sendPacket(new BackendboundBlockEntityPacket(Vector3i.from(x, y, z))); - return; - } - - // Without direct server access, we can't get lectern information on-the-fly. - // I should have set this up so it's only called when there is a book in the block state. - Camotoy - NbtMapBuilder lecternTag = LecternUtils.getBaseLecternTag(x, y, z, 1); - lecternTag.putCompound("book", NbtMap.builder() - .putByte("Count", (byte) 1) - .putShort("Damage", (short) 0) - .putString("Name", "minecraft:written_book") - .putCompound("tag", NbtMap.builder() - .putString("photoname", "") - .putString("text", "") - .build()) - .build()); - lecternTag.putInt("page", -1); // I'm surprisingly glad this exists - it forces Bedrock to stop reading immediately. Usually. - BlockEntityUtils.updateBlockEntity(session, lecternTag.build(), Vector3i.from(x, y, z)); - } - - @Override - public boolean shouldExpectLecternHandled(GeyserSession session) { - return session.getErosionHandler().isActive(); - } - @Override public void setGameRule(GeyserSession session, String name, Object value) { super.setGameRule(session, name, value); 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 6cd9c3e26..3670b6b73 100644 --- a/core/src/main/java/org/geysermc/geyser/level/WorldManager.java +++ b/core/src/main/java/org/geysermc/geyser/level/WorldManager.java @@ -40,11 +40,9 @@ import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponen 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.ItemCodecHelper; -import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityInfo; import org.geysermc.mcprotocollib.protocol.data.game.setting.Difficulty; import java.util.HashMap; -import java.util.List; import java.util.Locale; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -118,40 +116,6 @@ public abstract class WorldManager { */ public abstract boolean hasOwnChunkCache(); - /** - * Sigh.
- * - * So, on Java Edition, the lectern is an inventory. Java opens it and gets the contents of the book there. - * On Bedrock, the lectern contents are part of the block entity tag. Therefore, Bedrock expects to have the contents - * of the lectern ready and present in the world. If the contents are not there, it takes at least two clicks for the - * lectern to update the tag and then present itself.
- * - * 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 - * @param x the x coordinate of the lectern - * @param y the y coordinate of the lectern - * @param z the z coordinate of the lectern - */ - public abstract void sendLecternData(GeyserSession session, int x, int y, int z); - - /** - * {@link #sendLecternData(GeyserSession, int, int, int)} but batched for chunks. - * - * @param x chunk x - * @param z chunk z - * @param blockEntityInfos a list of coordinates (chunk local) to grab lecterns from. - */ - public abstract void sendLecternData(GeyserSession session, int x, int z, List blockEntityInfos); - - /** - * @return whether we should expect lectern data to update, or if we have to fall back on a workaround. - */ - public abstract boolean shouldExpectLecternHandled(GeyserSession session); - /** * Updates a gamerule value on the Java server * diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java b/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java index 9fe70c0f1..ee99b652a 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java @@ -91,39 +91,35 @@ public class Block { BlockDefinition definition = session.getBlockMappings().getBedrockBlock(state); sendBlockUpdatePacket(session, state, definition, position); - { - // Extended collision boxes for custom blocks - if (!session.getBlockMappings().getExtendedCollisionBoxes().isEmpty()) { - int aboveBlock = session.getGeyser().getWorldManager().getBlockAt(session, position.getX(), position.getY() + 1, position.getZ()); - BlockDefinition aboveBedrockExtendedCollisionDefinition = session.getBlockMappings().getExtendedCollisionBoxes().get(state.javaId()); - int belowBlock = session.getGeyser().getWorldManager().getBlockAt(session, position.getX(), position.getY() - 1, position.getZ()); - BlockDefinition belowBedrockExtendedCollisionDefinition = session.getBlockMappings().getExtendedCollisionBoxes().get(belowBlock); - if (belowBedrockExtendedCollisionDefinition != null && state.is(Blocks.AIR)) { - UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); - updateBlockPacket.setDataLayer(0); - updateBlockPacket.setBlockPosition(position); - updateBlockPacket.setDefinition(belowBedrockExtendedCollisionDefinition); - updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); - session.sendUpstreamPacket(updateBlockPacket); - } else if (aboveBedrockExtendedCollisionDefinition != null && aboveBlock == Block.JAVA_AIR_ID) { - UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); - updateBlockPacket.setDataLayer(0); - updateBlockPacket.setBlockPosition(position.add(0, 1, 0)); - updateBlockPacket.setDefinition(aboveBedrockExtendedCollisionDefinition); - updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); - session.sendUpstreamPacket(updateBlockPacket); - } else if (aboveBlock == Block.JAVA_AIR_ID) { - UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); - updateBlockPacket.setDataLayer(0); - updateBlockPacket.setBlockPosition(position.add(0, 1, 0)); - updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockAir()); - updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); - session.sendUpstreamPacket(updateBlockPacket); - } + // Extended collision boxes for custom blocks + if (!session.getBlockMappings().getExtendedCollisionBoxes().isEmpty()) { + int aboveBlock = session.getGeyser().getWorldManager().getBlockAt(session, position.getX(), position.getY() + 1, position.getZ()); + BlockDefinition aboveBedrockExtendedCollisionDefinition = session.getBlockMappings().getExtendedCollisionBoxes().get(state.javaId()); + int belowBlock = session.getGeyser().getWorldManager().getBlockAt(session, position.getX(), position.getY() - 1, position.getZ()); + BlockDefinition belowBedrockExtendedCollisionDefinition = session.getBlockMappings().getExtendedCollisionBoxes().get(belowBlock); + if (belowBedrockExtendedCollisionDefinition != null && state.is(Blocks.AIR)) { + UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); + updateBlockPacket.setDataLayer(0); + updateBlockPacket.setBlockPosition(position); + updateBlockPacket.setDefinition(belowBedrockExtendedCollisionDefinition); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); + session.sendUpstreamPacket(updateBlockPacket); + } else if (aboveBedrockExtendedCollisionDefinition != null && aboveBlock == Block.JAVA_AIR_ID) { + UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); + updateBlockPacket.setDataLayer(0); + updateBlockPacket.setBlockPosition(position.add(0, 1, 0)); + updateBlockPacket.setDefinition(aboveBedrockExtendedCollisionDefinition); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); + session.sendUpstreamPacket(updateBlockPacket); + } else if (aboveBlock == Block.JAVA_AIR_ID) { + UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); + updateBlockPacket.setDataLayer(0); + updateBlockPacket.setBlockPosition(position.add(0, 1, 0)); + updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockAir()); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); + session.sendUpstreamPacket(updateBlockPacket); } } - - handleLecternBlockUpdate(session, state, position); } protected void sendBlockUpdatePacket(GeyserSession session, BlockState state, BlockDefinition definition, Vector3i position) { @@ -153,13 +149,6 @@ public class Block { } } - protected void handleLecternBlockUpdate(GeyserSession session, BlockState state, Vector3i position) { - // Block state is out of bounds of this map - lectern has been destroyed, if it existed - if (!session.getGeyser().getWorldManager().shouldExpectLecternHandled(session)) { - session.getLecternCache().remove(position); - } - } - public Item asItem() { if (this.item == null) { return this.item = Item.byBlock(this); diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java index a312a7d5a..36c31f32e 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java @@ -56,6 +56,15 @@ public final class BlockState { return (T) get(property); } + public > T getValueNullable(Property property) { + var value = get(property); + if (value == null) { + return null; + } + //noinspection unchecked + return (T) get(property); + } + public boolean getValue(Property property, boolean def) { var value = get(property); if (value == null) { diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/LecternBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/LecternBlock.java index 6b8aa02b5..3139bd6de 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/LecternBlock.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/LecternBlock.java @@ -27,35 +27,67 @@ package org.geysermc.geyser.level.block.type; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; -import org.geysermc.erosion.util.LecternUtils; +import org.cloudburstmc.nbt.NbtMapBuilder; +import org.cloudburstmc.nbt.NbtType; import org.geysermc.geyser.level.WorldManager; import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.level.block.entity.BedrockChunkWantsBlockEntityTag; +import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator; import org.geysermc.geyser.util.BlockEntityUtils; -public class LecternBlock extends Block { +import java.util.Collections; + +public class LecternBlock extends Block implements BedrockChunkWantsBlockEntityTag { public LecternBlock(String javaIdentifier, Builder builder) { super(javaIdentifier, builder); } @Override - protected void handleLecternBlockUpdate(GeyserSession session, BlockState state, Vector3i position) { - WorldManager worldManager = session.getGeyser().getWorldManager(); - if (worldManager.shouldExpectLecternHandled(session)) { - worldManager.sendLecternData(session, position.getX(), position.getY(), position.getZ()); - return; - } + public NbtMap createTag(GeyserSession session, Vector3i position, BlockState blockState) { + return getBaseLecternTag(position, blockState.getValue(Properties.HAS_BOOK)); + } + @Override + public void updateBlock(GeyserSession session, BlockState state, Vector3i position) { + WorldManager worldManager = session.getGeyser().getWorldManager(); boolean currentHasBook = state.getValue(Properties.HAS_BOOK); - Boolean previousHasBook = worldManager.blockAt(session, position).getValue(Properties.HAS_BOOK); // Can be null if not a lectern, watch out - if (currentHasBook != previousHasBook) { - if (currentHasBook) { - worldManager.sendLecternData(session, position.getX(), position.getY(), position.getZ()); - } else { - session.getLecternCache().remove(position); - NbtMap newLecternTag = LecternUtils.getBaseLecternTag(position.getX(), position.getY(), position.getZ(), 0).build(); - BlockEntityUtils.updateBlockEntity(session, newLecternTag, position); - } + Boolean previousHasBook = worldManager.blockAt(session, position).getValueNullable(Properties.HAS_BOOK); // Can be null if not a lectern, watch out + if (previousHasBook == null || currentHasBook != previousHasBook) { + BlockEntityUtils.updateBlockEntity(session, getBaseLecternTag(position, currentHasBook), position); + } + super.updateBlock(session, state, position); + } + + public static NbtMap getBaseLecternTag(Vector3i position, boolean hasBook) { + if (hasBook) { + return getBaseLecternTag(position, 1) + .putCompound("book", NbtMap.builder() + .putByte("Count", (byte) 1) + .putShort("Damage", (short) 0) + .putString("Name", "minecraft:writable_book") + .putCompound("tag", NbtMap.builder().putList("pages", NbtType.COMPOUND, Collections.singletonList( + NbtMap.builder() + .putString("photoname", "") + .putString("text", "") + .build() + )).build()) + .build()) + .build(); + } else { + return getBaseLecternTag(position, 0).build(); } } + + public static NbtMapBuilder getBaseLecternTag(Vector3i position, int pages) { + NbtMapBuilder builder = BlockEntityTranslator.getConstantBedrockTag("Lectern", position); + builder.putBoolean("isMovable", true); + + if (pages != 0) { + builder.putByte("hasBook", (byte) 1); + builder.putInt("totalPages", 1); // we'll override it anyway + } + + return builder; + } } 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 9d2a3ef06..17010e966 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,6 @@ import org.geysermc.geyser.inventory.recipe.GeyserStonecutterData; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.BlockItem; import org.geysermc.geyser.level.JavaDimension; -import org.geysermc.geyser.level.WorldManager; import org.geysermc.geyser.level.physics.CollisionManager; import org.geysermc.geyser.network.netty.LocalSession; import org.geysermc.geyser.registry.Registries; @@ -257,13 +256,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { */ private final Map itemFrameCache = new Object2ObjectOpenHashMap<>(); - /** - * Stores a list of all lectern locations and their block entity tags. - * See {@link WorldManager#sendLecternData(GeyserSession, int, int, int)} - * for more information. - */ - private final @Nullable Set lecternCache; - /** * A list of all players that have a player head on with a custom texture. * Our workaround for these players is to give them a custom skin and geometry to emulate wearing a custom skull. @@ -609,13 +601,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { this.spawned = false; this.loggedIn = false; - if (geyser.getWorldManager().shouldExpectLecternHandled(this)) { - // Unneeded on these platforms - this.lecternCache = null; - } else { - this.lecternCache = new ObjectOpenHashSet<>(); - } - if (geyser.getConfig().getEmoteOffhandWorkaround() != EmoteOffhandWorkaroundOption.NO_EMOTES) { this.emotes = new HashSet<>(); geyser.getSessionManager().getSessions().values().forEach(player -> this.emotes.addAll(player.getEmotes())); 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 8fe1e96c0..3b33f5909 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 @@ -28,13 +28,18 @@ package org.geysermc.geyser.translator.inventory; 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.inventory.ItemData; import org.geysermc.erosion.util.LecternUtils; import org.geysermc.geyser.GeyserImpl; -import org.geysermc.geyser.inventory.*; +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.ContainerInventoryUpdater; import org.geysermc.geyser.level.block.Blocks; +import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.geyser.level.block.type.LecternBlock; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.BlockEntityUtils; import org.geysermc.geyser.util.InventoryUtils; @@ -44,8 +49,6 @@ import org.geysermc.mcprotocollib.protocol.data.game.item.component.WritableBook import org.geysermc.mcprotocollib.protocol.data.game.item.component.WrittenBookContent; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket; -import java.util.Collections; - public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator { /** @@ -95,7 +98,10 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator // Now: Restore the lectern, if it actually exists if (lecternContainer.isUsingRealBlock()) { - GeyserImpl.getInstance().getWorldManager().sendLecternData(session, position.getX(), position.getY(), position.getZ()); + boolean hasBook = session.getGeyser().getWorldManager().blockAt(session, position).getValue(Properties.HAS_BOOK, false); + + NbtMap map = LecternBlock.getBaseLecternTag(position, hasBook); + BlockEntityUtils.updateBlockEntity(session, map, position); } } @@ -148,7 +154,8 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator session.setDroppingLecternBook(false); InventoryUtils.closeInventory(session, inventory.getJavaId(), false); } else if (lecternContainer.getBlockEntityTag() == null) { - Vector3i position = lecternContainer.isUsingRealBlock() ? session.getLastInteractionBlockPosition() : inventory.getHolderPosition(); + Vector3i position = lecternContainer.isUsingRealBlock() ? + session.getLastInteractionBlockPosition() : inventory.getHolderPosition(); NbtMap blockEntityTag; if (book.getComponents() != null) { @@ -164,7 +171,7 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator } ItemData itemData = book.getItemData(session); - NbtMapBuilder lecternTag = LecternUtils.getBaseLecternTag(position.getX(), position.getY(), position.getZ(), pages); + NbtMapBuilder lecternTag = LecternBlock.getBaseLecternTag(position, pages); lecternTag.putCompound("book", NbtMap.builder() .putByte("Count", (byte) itemData.getCount()) .putShort("Damage", (short) 0) @@ -175,19 +182,7 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator blockEntityTag = lecternTag.build(); } else { // There is *a* book here, but... no NBT. - NbtMapBuilder lecternTag = LecternUtils.getBaseLecternTag(position.getX(), position.getY(), position.getZ(), 1); - NbtMapBuilder bookTag = NbtMap.builder() - .putByte("Count", (byte) 1) - .putShort("Damage", (short) 0) - .putString("Name", "minecraft:writable_book") - .putCompound("tag", NbtMap.builder().putList("pages", NbtType.COMPOUND, Collections.singletonList( - NbtMap.builder() - .putString("photoname", "") - .putString("text", "") - .build() - )).build()); - - blockEntityTag = lecternTag.putCompound("book", bookTag.build()).build(); + blockEntityTag = LecternBlock.getBaseLecternTag(position, true); } // Even with serverside access to lecterns, we don't easily know which lectern this is, so we need to rebuild 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 b0abe0f59..e687e6f46 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 @@ -33,7 +33,6 @@ import org.geysermc.geyser.util.ChunkUtils; import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundForgetLevelChunkPacket; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; @Translator(packet = ClientboundForgetLevelChunkPacket.class) @@ -52,17 +51,6 @@ public class JavaForgetLevelChunkTranslator extends PacketTranslator iterator = session.getLecternCache().iterator(); - while (iterator.hasNext()) { - Vector3i position = iterator.next(); - if ((position.getX() >> 4) == packet.getX() && (position.getZ() >> 4) == packet.getZ()) { - iterator.remove(); - } - } - } - ChunkUtils.sendEmptyChunk(session, packet.getX(), packet.getZ(), false); } } 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 18d12422e..e37edef66 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 @@ -34,14 +34,11 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NBTOutputStream; import org.cloudburstmc.nbt.NbtMap; -import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtUtils; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.packet.LevelChunkPacket; -import org.geysermc.erosion.util.LecternUtils; import org.geysermc.geyser.entity.type.ItemFrameEntity; import org.geysermc.geyser.level.BedrockDimension; -import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.level.chunk.BlockStorage; @@ -98,7 +95,6 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator bedrockBlockEntities = new ObjectArrayList<>(blockEntities.length); - final List lecterns = new ObjectArrayList<>(); BitSet waterloggedPaletteIds = new BitSet(); BitSet bedrockOnlyBlockEntityIds = new BitSet(); @@ -318,7 +314,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator> 4) - yOffset]; BlockState blockState = BlockRegistries.BLOCK_STATES.get(section.get(x, y & 0xF, z)); - if (type == BlockEntityType.LECTERN && blockState.getValue(Properties.HAS_BOOK)) { - // If getLecternBookStates is false, let's just treat it like a normal block entity - // Fill in tag with a default value - NbtMapBuilder lecternTag = LecternUtils.getBaseLecternTag(x + chunkBlockX, y, z + chunkBlockZ, 1); - lecternTag.putCompound("book", NbtMap.builder() - .putByte("Count", (byte) 1) - .putShort("Damage", (short) 0) - .putString("Name", "minecraft:written_book").build()); - lecternTag.putInt("page", -1); - bedrockBlockEntities.add(lecternTag.build()); - lecterns.add(blockEntity); - continue; - } - // Note that, since 1.20.5, tags can be null, but Bedrock still needs a default tag to render the item // Also, some properties - like banner base colors - are part of the tag and is processed here. BlockEntityTranslator blockEntityTranslator = BlockEntityUtils.getBlockEntityTranslator(type); @@ -525,10 +507,6 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator entry : session.getItemFrameCache().entrySet()) { Vector3i position = entry.getKey(); if ((position.getX() >> 4) == packet.getX() && (position.getZ() >> 4) == packet.getZ()) { 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 54e1cc34a..8446a340a 100644 --- a/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java @@ -65,9 +65,6 @@ public class DimensionUtils { session.getChunkCache().clear(); session.getEntityCache().removeAllEntities(); session.getItemFrameCache().clear(); - if (session.getLecternCache() != null) { - session.getLecternCache().clear(); - } session.getLodestoneCache().clear(); session.getPistonCache().clear(); session.getSkullCache().clear(); 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 d253d2f8b..48ade52e2 100644 --- a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java @@ -479,7 +479,6 @@ 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; From 7ba95f1ad3715c2e9fe3676c44ed18659c64b097 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Tue, 28 May 2024 00:11:05 -0700 Subject: [PATCH 042/233] Composite gradle setup and artifact archival (#4696) * Composite gradle setup and artifact archival * Remove 'geyser' path for PRs * Move upload-preview workflow --- .github/workflows/build-remote.yml | 85 +++++-------------------- .github/workflows/build.yml | 86 +++++--------------------- .github/workflows/dispatch-preview.yml | 33 ++++++++++ .github/workflows/preview.yml | 83 ------------------------- .github/workflows/pull-request.yml | 16 ++++- 5 files changed, 77 insertions(+), 226 deletions(-) create mode 100644 .github/workflows/dispatch-preview.yml delete mode 100644 .github/workflows/preview.yml diff --git a/.github/workflows/build-remote.yml b/.github/workflows/build-remote.yml index c815b4740..7cb89cc61 100644 --- a/.github/workflows/build-remote.yml +++ b/.github/workflows/build-remote.yml @@ -22,81 +22,26 @@ jobs: run: | echo "BUILD_NUMBER=${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV - - name: Setup Java - # See https://github.com/actions/setup-java/commits - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 - with: - java-version: 21 - distribution: temurin - - - name: Checkout repository and submodules - # See https://github.com/actions/checkout/commits - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - with: - repository: ${{ inputs.repository }} - ref: ${{ inputs.ref }} - submodules: recursive - - - name: Validate Gradle Wrapper - # See https://github.com/gradle/wrapper-validation-action/commits - uses: gradle/actions/wrapper-validation@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 - - name: Setup Gradle - # See https://github.com/gradle/actions/commits - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: GeyserMC/actions/setup-gradle-composite@master with: - cache-read-only: true + checkout_repository: ${{ inputs.repository }} + checkout_ref: ${{ inputs.ref }} + setup-java_java-version: 21 + setup-gradle_cache-read-only: true - name: Build Geyser run: ./gradlew build - - name: Archive artifacts (Geyser Fabric) - # See https://github.com/actions/upload-artifact/commits - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + - name: Archive Artifacts + uses: GeyserMC/actions/upload-multi-artifact@master 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@65462800fd760344b1a7b4382951275a0abb4808 - 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@65462800fd760344b1a7b4382951275a0abb4808 - 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@65462800fd760344b1a7b4382951275a0abb4808 - 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@65462800fd760344b1a7b4382951275a0abb4808 - 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@65462800fd760344b1a7b4382951275a0abb4808 - 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@65462800fd760344b1a7b4382951275a0abb4808 - if: success() - with: - name: Geyser ViaProxy - path: geyser/bootstrap/viaproxy/build/libs/Geyser-ViaProxy.jar - if-no-files-found: error \ No newline at end of file + artifacts: | + bootstrap/mod/fabric/build/libs/Geyser-Fabric.jar + bootstrap/mod/neoforge/build/libs/Geyser-NeoForge.jar + bootstrap/standalone/build/libs/Geyser-Standalone.jar + bootstrap/spigot/build/libs/Geyser-Spigot.jar + bootstrap/bungeecord/build/libs/Geyser-BungeeCord.jar + bootstrap/velocity/build/libs/Geyser-Velocity.jar + bootstrap/viaproxy/build/libs/Geyser-ViaProxy.jar \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f2f2a2c82..b8f855a53 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,84 +28,28 @@ jobs: with: data: ${{ vars.RELEASEACTION_PREVRELEASE }} - - name: Checkout repository and submodules - # See https://github.com/actions/checkout/commits - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - with: - submodules: recursive - - - name: Validate Gradle Wrapper - # See https://github.com/gradle/actions/commits - uses: gradle/actions/wrapper-validation@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 - - # See https://github.com/actions/setup-java/commits - - name: Setup Java - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 - with: - java-version: 21 - distribution: temurin - - name: Setup Gradle - # See https://github.com/gradle/actions/commits - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: GeyserMC/actions/setup-gradle-composite@master with: - gradle-home-cache-cleanup: true + setup-java_java-version: 21 - name: Build Geyser run: ./gradlew build env: BUILD_NUMBER: ${{ steps.release-info.outputs.curentRelease }} - - name: Archive artifacts (Geyser Fabric) - # See https://github.com/actions/upload-artifact/commits - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + - name: Archive Artifacts + uses: GeyserMC/actions/upload-multi-artifact@master 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@65462800fd760344b1a7b4382951275a0abb4808 - 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@65462800fd760344b1a7b4382951275a0abb4808 - 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@65462800fd760344b1a7b4382951275a0abb4808 - 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@65462800fd760344b1a7b4382951275a0abb4808 - 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@65462800fd760344b1a7b4382951275a0abb4808 - 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@65462800fd760344b1a7b4382951275a0abb4808 - if: success() - with: - name: Geyser ViaProxy - path: bootstrap/viaproxy/build/libs/Geyser-ViaProxy.jar - if-no-files-found: error + artifacts: | + bootstrap/mod/fabric/build/libs/Geyser-Fabric.jar + bootstrap/mod/neoforge/build/libs/Geyser-NeoForge.jar + bootstrap/standalone/build/libs/Geyser-Standalone.jar + bootstrap/spigot/build/libs/Geyser-Spigot.jar + bootstrap/bungeecord/build/libs/Geyser-BungeeCord.jar + bootstrap/velocity/build/libs/Geyser-Velocity.jar + bootstrap/viaproxy/build/libs/Geyser-ViaProxy.jar - name: Publish to Maven Repository if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} @@ -116,14 +60,14 @@ jobs: ORG_GRADLE_PROJECT_geysermcPassword: ${{ secrets.DEPLOY_PASS }} - name: Get Version - if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} + if: ${{ (success() || failure()) && github.repository == 'GeyserMC/Geyser' }} id: get-version run: | version=$(cat gradle.properties | grep -o "version=[0-9\\.]*" | cut -d"=" -f2) echo "VERSION=${version}" >> $GITHUB_OUTPUT - name: Get Release Metadata - if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} + if: ${{ (success() || failure()) && github.repository == 'GeyserMC/Geyser' }} uses: GeyserMC/actions/release@master id: metadata with: @@ -141,6 +85,7 @@ jobs: saveMetadata: true releaseProject: 'geyser' releaseVersion: ${{ steps.get-version.outputs.VERSION }} + - name: Publish to Downloads API if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} uses: GeyserMC/actions/upload-release@master @@ -156,6 +101,7 @@ jobs: bootstrap/standalone/build/libs/Geyser-Standalone.jar bootstrap/velocity/build/libs/Geyser-Velocity.jar bootstrap/viaproxy/build/libs/Geyser-ViaProxy.jar + changelog: ${{ steps.metadata.outputs.body }} - name: Publish to Modrinth (Fabric) if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} diff --git a/.github/workflows/dispatch-preview.yml b/.github/workflows/dispatch-preview.yml new file mode 100644 index 000000000..83df08e37 --- /dev/null +++ b/.github/workflows/dispatch-preview.yml @@ -0,0 +1,33 @@ +name: Dispatch 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: + dispatch-preview: + # Allow access to secrets if we are uploading a preview + secrets: inherit + uses: GeyserMC/actions/.github/workflows/upload-preview.yml@master + with: + build: ${{ inputs.build }} + version: ${{ inputs.version }} + 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 + project: geyserpreview + runId: ${{ inputs.runId }} \ No newline at end of file diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml deleted file mode 100644 index a90d60ef7..000000000 --- a/.github/workflows/preview.yml +++ /dev/null @@ -1,83 +0,0 @@ -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' - 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 - steps: - - 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_OUTPUT - echo "RUN=${{ github.event.inputs.runId }}" >> $GITHUB_OUTPUT - else - echo "BUILD=${{ inputs.build }}" >> $GITHUB_ENV - echo "VERSION=${{ inputs.version }}" >> $GITHUB_OUTPUT - echo "RUN=${{ github.run_id }}" >> $GITHUB_OUTPUT - fi - - name: Download Artifacts - # See https://github.com/actions/download-artifact/commits - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.6 - with: - run-id: ${{ steps.setvars.outputs.RUN }} - github-token: ${{ secrets.GITHUB_TOKEN }} - merge-multiple: true - - name: Get Preview Metadata - if: success() - uses: GeyserMC/actions/release@master - id: metadata - 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 - releaseProject: 'geyserpreview' - releaseVersion: ${{ steps.setvars.outputs.VERSION }} - - name: Publish to Downloads API - if: success() - uses: GeyserMC/actions/upload-release@master - with: - username: ${{ vars.DOWNLOADS_USERNAME }} - privateKey: ${{ secrets.DOWNLOADS_PRIVATE_KEY }} - host: ${{ secrets.DOWNLOADS_SERVER_IP }} - files: | - Geyser-BungeeCord.jar - Geyser-Fabric.jar - Geyser-NeoForge.jar - Geyser-Spigot.jar - Geyser-Standalone.jar - Geyser-Velocity.jar - Geyser-ViaProxy.jar diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index bc5e57b6b..6167bb18e 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -8,7 +8,7 @@ jobs: # Forbid access to secrets nor GH Token perms while building the PR permissions: {} secrets: {} - uses: ./.github/workflows/build-remote.yml + uses: GeyserMC/Geyser/.github/workflows/build-remote.yml@master with: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.event.pull_request.head.sha }} @@ -18,7 +18,17 @@ jobs: 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 + uses: GeyserMC/actions/.github/workflows/upload-preview.yml@master with: build: ${{ github.run_number }} - version: pr.${{ github.event.pull_request.number }} \ No newline at end of file + version: pr.${{ github.event.pull_request.number }} + 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 + project: geyserpreview + runId: ${{ github.run_id }} \ No newline at end of file From dc154915f0637ec02c04ef582f30e5ca0f4b814f Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Wed, 29 May 2024 01:48:33 -0700 Subject: [PATCH 043/233] Only include downloads on master --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b8f855a53..0e94ce965 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -124,3 +124,4 @@ jobs: discordWebhook: ${{ secrets.DISCORD_WEBHOOK }} status: ${{ job.status }} body: ${{ steps.metadata.outputs.body }} + includeDownloads: ${{ github.ref_name == 'master' }} From 8be60b41bf64e9dfec184d9047aa604bb7836b2a Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Wed, 29 May 2024 22:36:38 +0200 Subject: [PATCH 044/233] Remove lectern/item frame dropping handling for pre 1.20.60 --- .../BedrockItemFrameDropItemTranslator.java | 57 ------------ .../BedrockLecternUpdateTranslator.java | 88 +++++++------------ 2 files changed, 34 insertions(+), 111 deletions(-) delete mode 100644 core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockItemFrameDropItemTranslator.java 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 deleted file mode 100644 index dff4631b0..000000000 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockItemFrameDropItemTranslator.java +++ /dev/null @@ -1,57 +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.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 - *

- * 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()); - if (entity != null) { - ServerboundInteractPacket interactPacket = new ServerboundInteractPacket(entity.getEntityId(), - InteractAction.ATTACK, Hand.MAIN_HAND, session.isSneaking()); - session.sendDownstreamGamePacket(interactPacket); - } - } -} 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 e6d3d4dce..31a2d74cf 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,6 @@ package org.geysermc.geyser.translator.protocol.bedrock; -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; @@ -38,6 +33,8 @@ 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; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClosePacket; /** * Used to translate moving pages, or closing the inventory @@ -47,61 +44,44 @@ public class BedrockLecternUpdateTranslator extends PacketTranslator currentJavaPage) { + for (int i = currentJavaPage; i < newJavaPage; i++) { + ServerboundContainerButtonClickPacket clickButtonPacket = new ServerboundContainerButtonClickPacket(session.getOpenInventory().getJavaId(), 2); + session.sendDownstreamGamePacket(clickButtonPacket); } - - // Send as many click button packets as we need to - // Java has the option to specify exact page numbers by adding 100 to the number, but buttonId variable - // is a byte when transmitted over the network and therefore this stops us at 128 - if (newJavaPage > currentJavaPage) { - for (int i = currentJavaPage; i < newJavaPage; i++) { - ServerboundContainerButtonClickPacket clickButtonPacket = new ServerboundContainerButtonClickPacket(session.getOpenInventory().getJavaId(), 2); - session.sendDownstreamGamePacket(clickButtonPacket); - } - } else { - for (int i = currentJavaPage; i > newJavaPage; i--) { - ServerboundContainerButtonClickPacket clickButtonPacket = new ServerboundContainerButtonClickPacket(session.getOpenInventory().getJavaId(), 1); - session.sendDownstreamGamePacket(clickButtonPacket); - } + } else { + for (int i = currentJavaPage; i > newJavaPage; i--) { + ServerboundContainerButtonClickPacket clickButtonPacket = new ServerboundContainerButtonClickPacket(session.getOpenInventory().getJavaId(), 1); + session.sendDownstreamGamePacket(clickButtonPacket); } } } From 66f30a2cb6f477ec8ff9d9aa34ec015a6cd6891d Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 29 May 2024 23:43:39 +0200 Subject: [PATCH 045/233] Ensure we send commands/chat the same way a Java client would (#4703) * Ensure we send commands/chat the same way a Java client would * yeet static import, move blank check --- .../BedrockCommandRequestTranslator.java | 12 ++++--- .../bedrock/BedrockTextTranslator.java | 11 ++++++- .../translator/text/MessageTranslator.java | 33 +++++++++++++++++++ 3 files changed, 50 insertions(+), 6 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 322d64cce..8d4df6f3f 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,8 +26,8 @@ package org.geysermc.geyser.translator.protocol.bedrock; import org.cloudburstmc.protocol.bedrock.packet.CommandRequestPacket; -import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; @@ -39,15 +39,17 @@ public class BedrockCommandRequestTranslator extends PacketTranslator { @Override public void translate(GeyserSession session, TextPacket packet) { - String message = MessageTranslator.convertToPlainText(packet.getMessage()); + // Java trims all messages, and then checks for the leading slash + String message = MessageTranslator.convertToPlainText( + MessageTranslator.normalizeSpace(packet.getMessage()) + ); if (message.isBlank()) { // Java Edition (as of 1.17.1) just doesn't pass on these messages, so... we won't either! return; } + if (message.startsWith("/")) { + // Yes, Java actually allows whitespaces before commands and will still see those as valid + BedrockCommandRequestTranslator.handleCommand(session, message.substring(1)); + return; + } + if (MessageTranslator.isTooLong(message, session)) { return; } 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 5a0121039..bf6fdd763 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 @@ -387,6 +387,39 @@ public class MessageTranslator { return false; } + /** + * Normalizes whitespaces - a thing a vanilla client apparently does with commands and chat messages. + */ + public static String normalizeSpace(String string) { + if (string == null || string.isEmpty()) { + return string; + } + final int size = string.length(); + final char[] newChars = new char[size]; + int count = 0; + int whitespacesCount = 0; + boolean startWhitespaces = true; + for (int i = 0; i < size; i++) { + final char actualChar = string.charAt(i); + final boolean isWhitespace = Character.isWhitespace(actualChar); + if (isWhitespace) { + if (whitespacesCount == 0 && !startWhitespaces) { + newChars[count++] = ' '; + } + whitespacesCount++; + } else { + startWhitespaces = false; + // Replace non-breaking spaces with regular spaces for normalization + newChars[count++] = (actualChar == '\u00A0' ? ' ' : actualChar); + whitespacesCount = 0; + } + } + if (startWhitespaces) { + return ""; + } + return new String(newChars, 0, count - (whitespacesCount > 0 ? 1 : 0)).trim(); + } + public static void init() { // no-op } From c8fbffb6383713f64fe8c4a902cd78332b02941a Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Wed, 29 May 2024 21:47:50 -0400 Subject: [PATCH 046/233] Piston head correct pick block behavior --- .../geysermc/geyser/level/block/Blocks.java | 2 +- .../level/block/type/PistonHeadBlock.java | 42 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/type/PistonHeadBlock.java diff --git a/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java index fa605c079..857a3fc13 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java @@ -315,7 +315,7 @@ public final class Blocks { public static final Block PISTON = register(new PistonBlock("piston", builder().destroyTime(1.5f).pushReaction(PistonBehavior.BLOCK) .booleanState(EXTENDED) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block PISTON_HEAD = register(new Block("piston_head", builder().destroyTime(1.5f).pushReaction(PistonBehavior.BLOCK) + public static final Block PISTON_HEAD = register(new PistonHeadBlock("piston_head", builder().destroyTime(1.5f).pushReaction(PistonBehavior.BLOCK) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .booleanState(SHORT) .enumState(PISTON_TYPE))); diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/PistonHeadBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/PistonHeadBlock.java new file mode 100644 index 000000000..8a6b4f41c --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/PistonHeadBlock.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 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.level.block.type; + +import org.geysermc.geyser.level.block.Blocks; +import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; + +public class PistonHeadBlock extends Block { + public PistonHeadBlock(String javaIdentifier, Builder builder) { + super(javaIdentifier, builder); + } + + @Override + public ItemStack pickItem(BlockState state) { + Block block = state.getValue(Properties.PISTON_TYPE).equals("sticky") ? Blocks.STICKY_PISTON : Blocks.PISTON; + return new ItemStack(block.asItem().javaId()); + } +} From da5d8006ad182b550392393bb68187677be36c30 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Thu, 30 May 2024 22:29:00 -0400 Subject: [PATCH 047/233] Add native offhand support for *some* items About 46 items are data-driven enough where we can tell Bedrock these items are permitted in the offhand. --- .../populator/ItemRegistryPopulator.java | 27 +++++++++++++++++++ core/src/main/resources/mappings | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) 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 5fcea504f..8f515c1cb 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,6 +38,7 @@ 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.nbt.NbtUtils; import org.cloudburstmc.protocol.bedrock.codec.v671.Bedrock_v671; import org.cloudburstmc.protocol.bedrock.codec.v685.Bedrock_v685; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; @@ -102,6 +103,13 @@ public class ItemRegistryPopulator { throw new AssertionError("Unable to load Java runtime item IDs", e); } + NbtMap vanillaComponents; + try (InputStream stream = bootstrap.getResourceOrThrow("mappings/item_components.nbt")) { + vanillaComponents = (NbtMap) NbtUtils.createGZIPReader(stream, true, true).readTag(); + } catch (Exception e) { + throw new AssertionError("Unable to load Bedrock item components", e); + } + boolean customItemsAllowed = GeyserImpl.getInstance().getConfig().isAddNonBedrockItems(); // List values here is important compared to HashSet - we need to preserve the order of what's given to us @@ -531,6 +539,25 @@ public class ItemRegistryPopulator { } } + for (Map.Entry entry : vanillaComponents.entrySet()) { + String id = entry.getKey(); + ItemDefinition definition = definitions.get(id); + if (definition == null) { + // Newer item most likely + GeyserImpl.getInstance().getLogger().debug( + "Skipping vanilla component " + id + " for protocol " + palette.protocolVersion() + ); + continue; + } + + NbtMapBuilder root = NbtMap.builder() + .putString("name", id) + .putInt("id", definition.getRuntimeId()) + .putCompound("components", (NbtMap) entry.getValue()); + + componentItemData.add(new ComponentItemData(id, root.build())); + } + // Register the item forms of custom blocks if (BlockRegistries.CUSTOM_BLOCKS.get().length != 0) { for (CustomBlockData customBlock : BlockRegistries.CUSTOM_BLOCKS.get()) { diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings index ec45f59c8..88e50df10 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit ec45f59c8590945c9226921ef7e339f510983dc1 +Subproject commit 88e50df1008916c266428ac11f76f07dc24638c5 From 214cc5a8240faa733ebf19682599fa3ab546198d Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sat, 1 Jun 2024 01:25:30 -0400 Subject: [PATCH 048/233] Initial changes for Java 1.21 --- core/src/main/java/org/geysermc/geyser/item/Items.java | 9 ++++++--- .../java/org/geysermc/geyser/network/GameProtocol.java | 2 +- .../geyser/registry/populator/Conversion685_671.java | 6 ++++++ 3 files changed, 13 insertions(+), 4 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 8c271a7bb..732ee558a 100644 --- a/core/src/main/java/org/geysermc/geyser/item/Items.java +++ b/core/src/main/java/org/geysermc/geyser/item/Items.java @@ -838,6 +838,7 @@ public final class Items { 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 BOWL = register(new Item("bowl", builder())); public static final Item APPLE = register(new Item("apple", builder())); public static final Item BOW = register(new Item("bow", builder().stackSize(1).maxDamage(384))); public static final Item ARROW = register(new ArrowItem("arrow", builder())); @@ -887,7 +888,6 @@ public final class Items { 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))); public static final Item STRING = register(new BlockItem("string", builder(), Blocks.TRIPWIRE)); public static final Item FEATHER = register(new Item("feather", builder())); @@ -1044,7 +1044,7 @@ public final class Items { public static final Item BLAZE_POWDER = register(new Item("blaze_powder", builder())); public static final Item MAGMA_CREAM = register(new Item("magma_cream", builder())); public static final Item BREWING_STAND = register(new BlockItem(builder(), Blocks.BREWING_STAND)); - public static final Item CAULDRON = register(new BlockItem(builder(), Blocks.CAULDRON, Blocks.LAVA_CAULDRON, Blocks.POWDER_SNOW_CAULDRON, Blocks.WATER_CAULDRON)); + public static final Item CAULDRON = register(new BlockItem(builder(), Blocks.CAULDRON, Blocks.LAVA_CAULDRON, Blocks.WATER_CAULDRON, Blocks.POWDER_SNOW_CAULDRON)); 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())); @@ -1132,7 +1132,7 @@ public final class Items { 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 MACE = register(new MaceItem("mace", builder().stackSize(1).maxDamage(500))); 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(builder(), Blocks.FLOWER_POT)); @@ -1211,6 +1211,8 @@ public final class Items { public static final Item MUSIC_DISC_CAT = register(new Item("music_disc_cat", builder().stackSize(1))); public static final Item MUSIC_DISC_BLOCKS = register(new Item("music_disc_blocks", builder().stackSize(1))); public static final Item MUSIC_DISC_CHIRP = register(new Item("music_disc_chirp", builder().stackSize(1))); + public static final Item MUSIC_DISC_CREATOR = register(new Item("music_disc_creator", builder().stackSize(1))); + public static final Item MUSIC_DISC_CREATOR_MUSIC_BOX = register(new Item("music_disc_creator_music_box", builder().stackSize(1))); public static final Item MUSIC_DISC_FAR = register(new Item("music_disc_far", builder().stackSize(1))); public static final Item MUSIC_DISC_MALL = register(new Item("music_disc_mall", builder().stackSize(1))); public static final Item MUSIC_DISC_MELLOHI = register(new Item("music_disc_mellohi", builder().stackSize(1))); @@ -1223,6 +1225,7 @@ public final class Items { public static final Item MUSIC_DISC_RELIC = register(new Item("music_disc_relic", builder().stackSize(1))); 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 MUSIC_DISC_PRECIPICE = register(new Item("music_disc_precipice", 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).attackDamage(9.0))); public static final Item PHANTOM_MEMBRANE = register(new Item("phantom_membrane", builder())); 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 1c58288c7..773f0ae32 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -106,7 +106,7 @@ public final class GameProtocol { * @return the supported Minecraft: Java Edition version names */ public static List getJavaVersions() { - return List.of("1.20.5", DEFAULT_JAVA_CODEC.getMinecraftVersion()); + return List.of(DEFAULT_JAVA_CODEC.getMinecraftVersion()); } /** diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion685_671.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion685_671.java index 250fd9d9f..3bb6b5faf 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion685_671.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion685_671.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.registry.populator; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; +import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.registry.type.GeyserMappingItem; @@ -41,10 +42,15 @@ public class Conversion685_671 { private static final List OMINOUS_BLOCKS = List.of("minecraft:trial_spawner", "minecraft:vault"); private static final List NEW_BLOCKS = Stream.of(NEW_CORAL_BLOCKS, NEW_DOUBLE_PLANTS, NEW_STONE_BLOCK_SLABS, NEW_TALLGRASSES).flatMap(List::stream).toList(); private static final List MODIFIED_BLOCKS = Stream.of(NEW_BLOCKS, OMINOUS_BLOCKS).flatMap(List::stream).toList(); + private static final List NEW_MUSIC_DISCS = List.of(Items.MUSIC_DISC_CREATOR, Items.MUSIC_DISC_CREATOR_MUSIC_BOX, Items.MUSIC_DISC_PRECIPICE); static GeyserMappingItem remapItem(@SuppressWarnings("unused") Item item, GeyserMappingItem mapping) { String identifer = mapping.getBedrockIdentifier(); + if (NEW_MUSIC_DISCS.contains(item)) { + return mapping.withBedrockIdentifier("minecraft:music_disc_otherside"); + } + if (!NEW_BLOCKS.contains(identifer)) { return mapping; } From 65fd409a0099be88abe31d00ba21903dbd92eed0 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sun, 2 Jun 2024 20:42:53 -0400 Subject: [PATCH 049/233] Painting re-implemented. Started on enchantments --- .../geyser/entity/type/PaintingEntity.java | 14 ++- .../living/animal/tameable/WolfEntity.java | 38 ++++---- .../org/geysermc/geyser/item/Enchantment.java | 47 +++++++++ .../geysermc/geyser/item/type/BannerItem.java | 4 +- .../geysermc/geyser/level/PaintingType.java | 32 +++++-- .../registry/populator/Conversion685_671.java | 2 +- .../geyser/session/GeyserSession.java | 14 ++- .../geyser/session/cache/RegistryCache.java | 13 ++- .../cache/registry/SimpleJavaRegistry.java | 5 + .../geysermc/geyser/text/TextDecoration.java | 96 ++++++++----------- ...BedrockInventoryTransactionTranslator.java | 6 +- .../BedrockMobEquipmentTranslator.java | 7 +- .../protocol/java/JavaRespawnTranslator.java | 2 +- .../translator/text/MessageTranslator.java | 22 +++-- gradle/libs.versions.toml | 2 +- 15 files changed, 187 insertions(+), 117 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/item/Enchantment.java 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 f5145c11f..6d0294783 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 @@ -30,6 +30,8 @@ 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.Holder; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.PaintingVariant; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ObjectEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction; @@ -49,8 +51,14 @@ public class PaintingEntity extends Entity { // Wait until we get the metadata needed } - public void setPaintingType(ObjectEntityMetadata entityMetadata) { - PaintingType type = PaintingType.getByPaintingType(entityMetadata.getValue()); + public void setPaintingType(ObjectEntityMetadata> entityMetadata) { + if (!entityMetadata.getValue().isId()) { + return; + } + PaintingType type = session.getRegistryCache().paintings().byId(entityMetadata.getValue().id()); + if (type == null) { + return; + } AddPaintingPacket addPaintingPacket = new AddPaintingPacket(); addPaintingPacket.setUniqueEntityId(geyserId); addPaintingPacket.setRuntimeEntityId(geyserId); @@ -79,7 +87,7 @@ public class PaintingEntity extends Entity { private Vector3f fixOffset(PaintingType paintingName) { Vector3f position = super.position; position = position.add(0.5, 0.5, 0.5); - double widthOffset = paintingName.getWidth() > 1 ? 0.5 : 0; + double widthOffset = paintingName.getWidth() > 1 && paintingName.getWidth() != 3 ? 0.5 : 0; double heightOffset = paintingName.getHeight() > 1 && paintingName.getHeight() != 3 ? 0.5 : 0; return switch (direction) { 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 4573f0e7a..57fb901b4 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 @@ -36,33 +36,25 @@ 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.session.cache.tags.ItemTag; 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.Holder; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.WolfVariant; 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.metadata.type.ObjectEntityMetadata; 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; -import java.util.Set; import java.util.UUID; public class WolfEntity extends TameableEntity { - /** - * A list of all foods a wolf can eat on Java Edition. - * Used to display interactive tag or particles if needed. - * TODO generate - */ - private static final Set WOLF_FOODS = Set.of(Items.PUFFERFISH, Items.TROPICAL_FISH, Items.CHICKEN, Items.COOKED_CHICKEN, - 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 = 14; // Red - default private boolean isCurseOfBinding = false; @@ -112,12 +104,14 @@ public class WolfEntity extends TameableEntity { } // 1.20.5+ - public void setWolfVariant(IntEntityMetadata entityMetadata) { - WolfVariant wolfVariant = session.getRegistryCache().wolfVariants().byId(entityMetadata.getPrimitiveValue()); - if (wolfVariant == null) { - wolfVariant = WolfVariant.PALE; - } - dirtyMetadata.put(EntityDataTypes.VARIANT, wolfVariant.ordinal()); + public void setWolfVariant(ObjectEntityMetadata> entityMetadata) { + entityMetadata.getValue().ifId(id -> { + BuiltInWolfVariant wolfVariant = session.getRegistryCache().wolfVariants().byId(id); + if (wolfVariant == null) { + wolfVariant = BuiltInWolfVariant.PALE; + } + dirtyMetadata.put(EntityDataTypes.VARIANT, wolfVariant.ordinal()); + }); } @Override @@ -187,7 +181,7 @@ public class WolfEntity extends TameableEntity { } // Ordered by bedrock id - public enum WolfVariant { + public enum BuiltInWolfVariant { PALE, ASHEN, BLACK, @@ -198,16 +192,16 @@ public class WolfEntity extends TameableEntity { STRIPED, WOODS; - private static final WolfVariant[] VALUES = values(); + private static final BuiltInWolfVariant[] VALUES = values(); private final String javaIdentifier; - WolfVariant() { + BuiltInWolfVariant() { this.javaIdentifier = "minecraft:" + this.name().toLowerCase(Locale.ROOT); } - public static @Nullable WolfVariant getByJavaIdentifier(String javaIdentifier) { - for (WolfVariant wolfVariant : VALUES) { + public static @Nullable BuiltInWolfVariant getByJavaIdentifier(String javaIdentifier) { + for (BuiltInWolfVariant wolfVariant : VALUES) { if (wolfVariant.javaIdentifier.equals(javaIdentifier)) { return wolfVariant; } diff --git a/core/src/main/java/org/geysermc/geyser/item/Enchantment.java b/core/src/main/java/org/geysermc/geyser/item/Enchantment.java new file mode 100644 index 000000000..506467afd --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/item/Enchantment.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 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; + +import org.checkerframework.checker.nullness.qual.Nullable; +import org.cloudburstmc.nbt.NbtMap; +import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; + +/** + * @param anvilCost also as a rarity multiplier + */ +public record Enchantment(String supportedItemsTag, int maxLevel, int anvilCost, @Nullable String exclusiveSetTag) { + + // Implementation note: I have a feeling the tags can be a list of items, because in vanilla they're HolderSet classes. + // I'm not sure how that's wired over the network, so we'll put it off. + public static Enchantment read(RegistryEntry entry) { + NbtMap data = entry.getData(); + String supportedItems = data.getString("supported_items"); + int maxLevel = data.getInt("max_level"); + int anvilCost = data.getInt("anvil_cost"); + String exclusiveSet = data.getString("exclusive_set", null); + return new Enchantment(supportedItems, maxLevel, anvilCost, exclusiveSet); + } +} 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 b53843882..cf0105622 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 @@ -146,8 +146,8 @@ public class BannerItem extends BlockItem { } else { List patternList = new ArrayList<>(patterns.size()); for (BannerPatternLayer patternLayer : patterns) { - patternLayer.getPattern().ifId(holder -> { - BannerPattern bannerPattern = session.getRegistryCache().bannerPatterns().byId(holder.id()); + patternLayer.getPattern().ifId(id -> { + BannerPattern bannerPattern = session.getRegistryCache().bannerPatterns().byId(id); if (bannerPattern != null) { NbtMap tag = NbtMap.builder() .putString("Pattern", bannerPattern.getBedrockIdentifier()) 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 643fd735d..de35d97f1 100644 --- a/core/src/main/java/org/geysermc/geyser/level/PaintingType.java +++ b/core/src/main/java/org/geysermc/geyser/level/PaintingType.java @@ -29,6 +29,8 @@ import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; +import java.util.Locale; + @AllArgsConstructor(access = AccessLevel.PRIVATE) @Getter public enum PaintingType { @@ -61,7 +63,27 @@ public enum PaintingType { EARTH("Earth", 2, 2), WIND("Wind", 2, 2), WATER("Water", 2, 2), - FIRE("Fire", 2, 2); + FIRE("Fire", 2, 2), + MEDITATIVE("meditative", 1, 1), + PRAIRIE_RIDE("prairie_ride", 1, 2), + BAROQUE("baroque", 2, 2), + HUMBLE("humble", 2, 2), + UNPACKED("unpacked", 4, 4), + BACKYARD("backyard", 3, 4), + BOUQUET("bouquet", 3, 3), + CAVEBIRD("cavebird", 3, 3), + CHANGING("changing", 4, 2), + COTAN("cotan", 3, 3), + ENDBOSS("endboss", 3, 3), + FERN("fern", 3, 3), + FINDING("finding", 4, 2), + LOWMIST("lowmist", 4, 2), + ORB("orb", 4, 4), + OWLEMONS("owlemons", 3, 3), + PASSAGE("passage", 4, 2), + POND("pond", 3, 4), + SUNFLOWERS("sunflowers", 3, 3), + TIDES("tides", 3, 3); private static final PaintingType[] VALUES = values(); private final String bedrockName; @@ -70,12 +92,8 @@ public enum PaintingType { public static PaintingType getByName(String javaName) { for (PaintingType paintingName : VALUES) { - if (paintingName.name().equalsIgnoreCase(javaName)) return paintingName; + if (("minecraft:" + paintingName.name().toLowerCase(Locale.ROOT)).equals(javaName)) return paintingName; } - return KEBAB; - } - - public static PaintingType getByPaintingType(org.geysermc.mcprotocollib.protocol.data.game.entity.type.PaintingType paintingType) { - return getByName(paintingType.name()); + return null; } } diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion685_671.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion685_671.java index 3bb6b5faf..c96966927 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion685_671.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion685_671.java @@ -44,7 +44,7 @@ public class Conversion685_671 { private static final List MODIFIED_BLOCKS = Stream.of(NEW_BLOCKS, OMINOUS_BLOCKS).flatMap(List::stream).toList(); private static final List NEW_MUSIC_DISCS = List.of(Items.MUSIC_DISC_CREATOR, Items.MUSIC_DISC_CREATOR_MUSIC_BOX, Items.MUSIC_DISC_PRECIPICE); - static GeyserMappingItem remapItem(@SuppressWarnings("unused") Item item, GeyserMappingItem mapping) { + static GeyserMappingItem remapItem(Item item, GeyserMappingItem mapping) { String identifer = mapping.getBedrockIdentifier(); if (NEW_MUSIC_DISCS.contains(item)) { 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 17010e966..9543c7943 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -1302,22 +1302,28 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { } } + /** + * Convenience method to reduce amount of duplicate code. Sends ServerboundUseItemPacket. + */ + public void useItem(Hand hand) { + sendDownstreamGamePacket(new ServerboundUseItemPacket( + hand, worldCache.nextPredictionSequence(), playerEntity.getPitch(), playerEntity.getYaw())); + } + /** * Checks to see if a shield is in either hand to activate blocking. If so, it sets the Bedrock client to display * blocking and sends a packet to the Java server. */ private boolean attemptToBlock() { - ServerboundUseItemPacket useItemPacket; if (playerInventory.getItemInHand().asItem() == Items.SHIELD) { - useItemPacket = new ServerboundUseItemPacket(Hand.MAIN_HAND, worldCache.nextPredictionSequence()); + useItem(Hand.MAIN_HAND); } else if (playerInventory.getOffhand().asItem() == Items.SHIELD) { - useItemPacket = new ServerboundUseItemPacket(Hand.OFF_HAND, worldCache.nextPredictionSequence()); + useItem(Hand.OFF_HAND); } else { // No blocking return false; } - sendDownstreamGamePacket(useItemPacket); playerEntity.setFlag(EntityFlag.BLOCKING, true); // Metadata should be updated later return true; 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 fa4503635..a9b14fdc0 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 @@ -38,7 +38,9 @@ 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.item.Enchantment; import org.geysermc.geyser.level.JavaDimension; +import org.geysermc.geyser.level.PaintingType; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.registry.JavaRegistry; import org.geysermc.geyser.session.cache.registry.SimpleJavaRegistry; @@ -46,6 +48,7 @@ import org.geysermc.geyser.text.TextDecoration; import org.geysermc.geyser.translator.level.BiomeTranslator; import org.geysermc.mcprotocollib.protocol.MinecraftProtocol; import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; +import org.geysermc.mcprotocollib.protocol.data.game.chat.ChatType; import org.geysermc.mcprotocollib.protocol.packet.configuration.clientbound.ClientboundRegistryDataPacket; import java.util.ArrayList; @@ -72,11 +75,13 @@ public final class RegistryCache { static { register("chat_type", cache -> cache.chatTypes, ($, entry) -> TextDecoration.readChatType(entry)); register("dimension_type", cache -> cache.dimensions, ($, entry) -> JavaDimension.read(entry)); + register("enchantment", cache -> cache.enchantments, ($, entry) -> Enchantment.read(entry)); + register("painting_variant", cache -> cache.paintings, ($, entry) -> PaintingType.getByName(entry.getId())); 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())); - register("wolf_variant", cache -> cache.wolfVariants, ($, entry) -> WolfEntity.WolfVariant.getByJavaIdentifier(entry.getId())); + register("wolf_variant", cache -> cache.wolfVariants, ($, entry) -> WolfEntity.BuiltInWolfVariant.getByJavaIdentifier(entry.getId())); // Load from MCProtocolLib's classloader NbtMap tag = MinecraftProtocol.loadNetworkCodec(); @@ -104,16 +109,18 @@ public final class RegistryCache { * Java -> Bedrock biome network IDs. */ private int[] biomeTranslations; - private final JavaRegistry chatTypes = new SimpleJavaRegistry<>(); + private final JavaRegistry chatTypes = new SimpleJavaRegistry<>(); /** * All dimensions that the client could possibly connect to. */ private final JavaRegistry dimensions = new SimpleJavaRegistry<>(); + private final JavaRegistry enchantments = new SimpleJavaRegistry<>(); + private final JavaRegistry paintings = new SimpleJavaRegistry<>(); private final JavaRegistry trimMaterials = new SimpleJavaRegistry<>(); private final JavaRegistry trimPatterns = new SimpleJavaRegistry<>(); private final JavaRegistry bannerPatterns = new SimpleJavaRegistry<>(); - private final JavaRegistry wolfVariants = new SimpleJavaRegistry<>(); + private final JavaRegistry wolfVariants = new SimpleJavaRegistry<>(); public RegistryCache(GeyserSession session) { this.session = session; 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 9839a1568..7b79a40be 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 @@ -57,4 +57,9 @@ public class SimpleJavaRegistry implements JavaRegistry { public List values() { return this.values; } + + @Override + public String toString() { + return this.values.toString(); + } } 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 b2222d3b9..cf2071173 100644 --- a/core/src/main/java/org/geysermc/geyser/text/TextDecoration.java +++ b/core/src/main/java/org/geysermc/geyser/text/TextDecoration.java @@ -30,21 +30,49 @@ 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 org.geysermc.mcprotocollib.protocol.data.game.chat.ChatType; +import org.geysermc.mcprotocollib.protocol.data.game.chat.ChatTypeDecoration; -import java.util.EnumSet; -import java.util.List; -import java.util.Locale; -import java.util.Set; +import java.util.*; -public final class TextDecoration { - private final String translationKey; - private final Style style; - private final Set parameters; +public record TextDecoration(String translationKey, List parameters, Style deserializedStyle) implements ChatTypeDecoration { - public TextDecoration(NbtMap tag) { - translationKey = tag.getString("translation_key"); + @Override + public NbtMap style() { + // Should not ever be called. + throw new UnsupportedOperationException(); + } - NbtMap styleTag = tag.getCompound("style"); + public static ChatType 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. + // (This note has been passed around through several classes and iterations. It stays as a warning + // to anyone that dares to try and hardcode registry IDs.) + NbtMap tag = entry.getData(); + NbtMap chat = tag.getCompound("chat", null); + if (chat != null) { + String translationKey = tag.getString("translation_key"); + + NbtMap styleTag = tag.getCompound("style"); + Style style = deserializeStyle(styleTag); + + List parameters = new ArrayList<>(); + List parametersNbt = tag.getList("parameters", NbtType.STRING); + for (String parameter : parametersNbt) { + parameters.add(ChatTypeDecoration.Parameter.valueOf(parameter.toUpperCase(Locale.ROOT))); + } + return new ChatType(new TextDecoration(translationKey, parameters, style), null); + } + return new ChatType(null, null); + } + + public static Style getStyle(ChatTypeDecoration decoration) { + if (decoration instanceof TextDecoration textDecoration) { + return textDecoration.deserializedStyle(); + } + return deserializeStyle(decoration.style()); + } + + private static Style deserializeStyle(NbtMap styleTag) { Style.Builder builder = Style.style(); if (!styleTag.isEmpty()) { String color = styleTag.getString("color", null); @@ -57,50 +85,6 @@ public final class TextDecoration { builder.decorate(net.kyori.adventure.text.format.TextDecoration.ITALIC); } } - style = builder.build(); - - this.parameters = EnumSet.noneOf(Parameter.class); - List parameters = tag.getList("parameters", NbtType.STRING); - for (String parameter : parameters) { - this.parameters.add(Parameter.valueOf(parameter.toUpperCase(Locale.ROOT))); - } - } - - public String translationKey() { - return translationKey; - } - - public Style style() { - return style; - } - - public Set parameters() { - return parameters; - } - - @Override - public String toString() { - return "TextDecoration{" + - "translationKey='" + translationKey + '\'' + - ", style=" + style + - ", parameters=" + parameters + - '}'; - } - - 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. - NbtMap tag = entry.getData(); - NbtMap chat = tag.getCompound("chat", null); - TextDecoration textDecoration = null; - if (chat != null) { - textDecoration = new TextDecoration(chat); - } - return textDecoration; - } - - public enum Parameter { - CONTENT, - SENDER, - TARGET + return builder.build(); } } 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 878d326ac..534a89e23 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 @@ -394,8 +394,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator legacySlots = packet.getLegacySlots(); if (packet.getActions().size() == 1 && !legacySlots.isEmpty()) { @@ -639,8 +638,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator session.sendDownstreamGamePacket(new ServerboundUseItemPacket(Hand.MAIN_HAND, session.getWorldCache().nextPredictionSequence())), + session.scheduleInEventLoop(() -> session.useItem(Hand.MAIN_HAND), 50, TimeUnit.MILLISECONDS); } 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 fe0868253..44ce51352 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 @@ -53,7 +53,7 @@ public class JavaRespawnTranslator extends PacketTranslator chatTypeHolder, Component targetName, Component sender) { TextPacket textPacket = new TextPacket(); textPacket.setPlatformChatId(""); textPacket.setSourceName(""); @@ -330,14 +333,15 @@ public class MessageTranslator { textPacket.setNeedsTranslation(false); - TextDecoration decoration = session.getRegistryCache().chatTypes().byId(chatType); - if (decoration != null) { + ChatType chatType = chatTypeHolder.getOrCompute(session.getRegistryCache().chatTypes()::byId); + if (chatType != null && chatType.chat() != null) { + var chat = chatType.chat(); // As of 1.19 - do this to apply all the styling for signed messages // Though, Bedrock cannot care about the signed stuff. TranslatableComponent.Builder withDecoration = Component.translatable() - .key(decoration.translationKey()) - .style(decoration.style()); - Set parameters = decoration.parameters(); + .key(chat.translationKey()) + .style(TextDecoration.getStyle(chat)); + List parameters = chat.parameters(); List args = new ArrayList<>(3); if (parameters.contains(TextDecoration.Parameter.TARGET)) { args.add(targetName); @@ -348,7 +352,7 @@ public class MessageTranslator { if (parameters.contains(TextDecoration.Parameter.CONTENT)) { args.add(message); } - withDecoration.args(args); + withDecoration.arguments(args); textPacket.setMessage(MessageTranslator.convertMessage(withDecoration.build(), session.locale())); } else { session.getGeyser().getLogger().debug("Likely illegal chat type detection found."); diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1995a6ada..f1b765e0f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ websocket = "1.5.1" protocol = "3.0.0.Beta2-20240520.153053-5" raknet = "1.0.0.CR3-20240416.144209-1" mcauthlib = "e5b0bcc" -mcprotocollib = "1.20.6-2-20240520.030045-8" +mcprotocollib = "1.21-SNAPSHOT" adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From 8ad10f8a9ea686043837d60057b70fdb83dc6321 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sun, 2 Jun 2024 23:36:44 -0400 Subject: [PATCH 050/233] Boats are leashable --- .../geyser/entity/type/BoatEntity.java | 23 +++++++++- .../geysermc/geyser/entity/type/Entity.java | 24 ++++++++++ .../geyser/entity/type/Leashable.java | 44 +++++++++++++++++++ .../entity/type/living/AmbientEntity.java | 2 +- .../entity/type/living/DolphinEntity.java | 2 +- .../geyser/entity/type/living/MobEntity.java | 27 +++++------- .../entity/type/living/SquidEntity.java | 2 +- .../entity/type/living/WaterEntity.java | 2 +- .../type/living/animal/AxolotlEntity.java | 2 +- .../type/living/animal/HoglinEntity.java | 2 +- .../type/living/animal/PandaEntity.java | 2 +- .../type/living/animal/TurtleEntity.java | 2 +- .../animal/tameable/TameableEntity.java | 2 +- .../living/animal/tameable/WolfEntity.java | 2 +- .../merchant/AbstractMerchantEntity.java | 2 +- .../type/living/monster/ZoglinEntity.java | 2 +- .../entity/JavaSetEntityLinkTranslator.java | 16 +++---- 17 files changed, 120 insertions(+), 38 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/entity/type/Leashable.java 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 d9a64ccc6..47ae6777a 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 @@ -41,7 +41,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; -public class BoatEntity extends Entity implements Tickable { +public class BoatEntity extends Entity implements Leashable, Tickable { /** * Required when IS_BUOYANT is sent in order for boats to work in the water.
@@ -65,6 +65,8 @@ public class BoatEntity extends Entity implements Tickable { @Getter private int variant; + private long leashHolderBedrockId = -1; + // 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.1f; @@ -147,8 +149,18 @@ public class BoatEntity extends Entity implements Tickable { } } + @Override + public void setLeashHolderBedrockId(long bedrockId) { + this.leashHolderBedrockId = bedrockId; + dirtyMetadata.put(EntityDataTypes.LEASH_HOLDER, bedrockId); + } + @Override protected InteractiveTag testInteraction(Hand hand) { + InteractiveTag tag = super.testInteraction(hand); + if (tag != InteractiveTag.NONE) { + return tag; + } if (session.isSneaking()) { return InteractiveTag.NONE; } else if (passengers.size() < 2) { @@ -160,6 +172,10 @@ public class BoatEntity extends Entity implements Tickable { @Override public InteractionResult interact(Hand hand) { + InteractionResult result = super.interact(hand); + if (result != InteractionResult.PASS) { + return result; + } if (session.isSneaking()) { return InteractionResult.PASS; } else { @@ -191,6 +207,11 @@ public class BoatEntity extends Entity implements Tickable { } } + @Override + public long leashHolderBedrockId() { + return leashHolderBedrockId; + } + private void sendAnimationPacket(GeyserSession session, Entity rower, AnimatePacket.Action action, float rowTime) { AnimatePacket packet = new AnimatePacket(); packet.setRuntimeEntityId(rower.getGeyserId()); 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 6267ee791..08e87dc03 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 @@ -40,6 +40,7 @@ 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.item.Items; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.util.EntityUtils; @@ -557,6 +558,17 @@ public class Entity implements GeyserEntity { * Should usually mirror {@link #interact(Hand)} without any side effects. */ protected InteractiveTag testInteraction(Hand hand) { + if (isAlive() && this instanceof Leashable leashable) { + if (leashable.leashHolderBedrockId() == session.getPlayerEntity().getGeyserId()) { + // Note this might be client side. Has yet to be an issue though, as of Java 1.21. + return InteractiveTag.REMOVE_LEASH; + } + if (session.getPlayerInventory().getItemInHand(hand).asItem() == Items.LEAD && leashable.canBeLeashed()) { + // We shall leash + return InteractiveTag.LEASH; + } + } + return InteractiveTag.NONE; } @@ -565,6 +577,18 @@ public class Entity implements GeyserEntity { * to ensure packet parity as well as functionality parity (such as sound effect responses). */ public InteractionResult interact(Hand hand) { + if (isAlive() && this instanceof Leashable leashable) { + if (leashable.leashHolderBedrockId() == session.getPlayerEntity().getGeyserId()) { + // Note this might also update client side (a theoretical Geyser/client desync and Java parity issue). + // Has yet to be an issue though, as of Java 1.21. + return InteractionResult.SUCCESS; + } + if (session.getPlayerInventory().getItemInHand(hand).asItem() == Items.LEAD && leashable.canBeLeashed()) { + // We shall leash + return InteractionResult.SUCCESS; + } + } + return InteractionResult.PASS; } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/Leashable.java b/core/src/main/java/org/geysermc/geyser/entity/type/Leashable.java new file mode 100644 index 000000000..64d95ba3c --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/entity/type/Leashable.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 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; + +/** + * I can haz lead + * (The item, not the mineral) + */ +public interface Leashable { + void setLeashHolderBedrockId(long bedrockId); + + long leashHolderBedrockId(); + + default boolean canBeLeashed() { + return isNotLeashed(); + } + + default boolean isNotLeashed() { + return leashHolderBedrockId() == -1L; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/AmbientEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/AmbientEntity.java index 8f81125d0..f4b80edf1 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/AmbientEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/AmbientEntity.java @@ -38,7 +38,7 @@ public class AmbientEntity extends MobEntity { } @Override - protected boolean canBeLeashed() { + public boolean canBeLeashed() { return false; } } 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 6182a27f4..a0ea79d67 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 @@ -43,7 +43,7 @@ public class DolphinEntity extends WaterEntity { } @Override - protected boolean canBeLeashed() { + public boolean canBeLeashed() { return true; } 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 95145ae60..9accf178f 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,12 +25,12 @@ package org.geysermc.geyser.entity.type.living; -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; import org.geysermc.geyser.entity.EntityDefinition; +import org.geysermc.geyser.entity.type.Leashable; import org.geysermc.geyser.entity.type.LivingEntity; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; @@ -43,11 +43,10 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; -public class MobEntity extends LivingEntity { +public class MobEntity extends LivingEntity implements Leashable { /** * If another mob is holding this mob by a leash, this variable tracks their Bedrock entity ID. */ - @Getter private long leashHolderBedrockId; public MobEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { @@ -65,6 +64,7 @@ public class MobEntity extends LivingEntity { setFlag(EntityFlag.NO_AI, (xd & 0x01) == 0x01); } + @Override public void setLeashHolderBedrockId(long bedrockId) { this.leashHolderBedrockId = bedrockId; dirtyMetadata.put(EntityDataTypes.LEASH_HOLDER, bedrockId); @@ -79,10 +79,7 @@ public class MobEntity extends LivingEntity { return InteractiveTag.REMOVE_LEASH; } else { GeyserItemStack itemStack = session.getPlayerInventory().getItemInHand(hand); - if (itemStack.asItem() == Items.LEAD && canBeLeashed()) { - // We shall leash - return InteractiveTag.LEASH; - } else if (itemStack.asItem() == Items.NAME_TAG) { + if (itemStack.asItem() == Items.NAME_TAG) { InteractionResult result = checkInteractWithNameTag(itemStack); if (result.consumesAction()) { return InteractiveTag.NAME; @@ -99,9 +96,6 @@ public class MobEntity extends LivingEntity { if (!isAlive()) { // dead lol return InteractionResult.PASS; - } else if (leashHolderBedrockId == session.getPlayerEntity().getGeyserId()) { - // TODO looks like the client assumes it will go through and removes the attachment itself? - return InteractionResult.SUCCESS; } else { GeyserItemStack itemInHand = session.getPlayerInventory().getItemInHand(hand); InteractionResult result = checkPriorityInteractions(itemInHand); @@ -115,10 +109,7 @@ public class MobEntity extends LivingEntity { } private InteractionResult checkPriorityInteractions(GeyserItemStack itemInHand) { - if (itemInHand.asItem() == Items.LEAD && canBeLeashed()) { - // We shall leash - return InteractionResult.SUCCESS; - } else if (itemInHand.asItem() == Items.NAME_TAG) { + if (itemInHand.asItem() == Items.NAME_TAG) { InteractionResult result = checkInteractWithNameTag(itemInHand); if (result.consumesAction()) { return result; @@ -143,12 +134,14 @@ public class MobEntity extends LivingEntity { return InteractionResult.PASS; } - protected boolean canBeLeashed() { + @Override + public boolean canBeLeashed() { return isNotLeashed() && !isEnemy(); } - protected final boolean isNotLeashed() { - return leashHolderBedrockId == -1L; + @Override + public long leashHolderBedrockId() { + return leashHolderBedrockId; } /** diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/SquidEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/SquidEntity.java index 80a5af442..6285bd9a4 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/SquidEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/SquidEntity.java @@ -122,7 +122,7 @@ public class SquidEntity extends WaterEntity implements Tickable { } @Override - protected boolean canBeLeashed() { + public boolean canBeLeashed() { return isNotLeashed(); } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/WaterEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/WaterEntity.java index a847c4cd7..ae9d0d659 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/WaterEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/WaterEntity.java @@ -38,7 +38,7 @@ public class WaterEntity extends CreatureEntity { } @Override - protected boolean canBeLeashed() { + public boolean canBeLeashed() { return false; } } 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 a87b1dd5e..a0ab56ead 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 @@ -72,7 +72,7 @@ public class AxolotlEntity extends AnimalEntity { } @Override - protected boolean canBeLeashed() { + public boolean canBeLeashed() { return true; } 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 74c937417..cc23fc607 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 @@ -63,7 +63,7 @@ public class HoglinEntity extends AnimalEntity { } @Override - protected boolean canBeLeashed() { + public boolean canBeLeashed() { return isNotLeashed(); } 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 79401f63f..aaa7c2d7e 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 @@ -123,7 +123,7 @@ public class PandaEntity extends AnimalEntity { } @Override - protected boolean canBeLeashed() { + public boolean canBeLeashed() { return false; } 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 b3c1128e3..16901a844 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 @@ -56,7 +56,7 @@ public class TurtleEntity extends AnimalEntity { } @Override - protected boolean canBeLeashed() { + public boolean canBeLeashed() { return false; } } 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 e16823d37..ea347d193 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 @@ -84,7 +84,7 @@ public abstract class TameableEntity extends AnimalEntity { } @Override - protected boolean canBeLeashed() { + public boolean canBeLeashed() { return isNotLeashed(); } } 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 57fb901b4..c6b8051e7 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 @@ -127,7 +127,7 @@ public class WolfEntity extends TameableEntity { } @Override - protected boolean canBeLeashed() { + public boolean canBeLeashed() { return !getFlag(EntityFlag.ANGRY) && super.canBeLeashed(); } 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 64e35e52e..2492aabd7 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 @@ -47,7 +47,7 @@ public class AbstractMerchantEntity extends AgeableEntity { } @Override - protected boolean canBeLeashed() { + public boolean canBeLeashed() { return false; } 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 206746fb9..3d6e381c7 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 @@ -58,7 +58,7 @@ public class ZoglinEntity extends MonsterEntity { } @Override - protected boolean canBeLeashed() { + public boolean canBeLeashed() { return isNotLeashed(); } 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 d595e928f..15d47a285 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,15 +25,15 @@ package org.geysermc.geyser.translator.protocol.java.entity; -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; import org.geysermc.geyser.entity.type.Entity; -import org.geysermc.geyser.entity.type.living.MobEntity; +import org.geysermc.geyser.entity.type.Leashable; 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.ClientboundSetEntityLinkPacket; /** * Called when a leash is attached, removed or updated from an entity @@ -44,16 +44,16 @@ public class JavaSetEntityLinkTranslator extends PacketTranslator Date: Mon, 3 Jun 2024 21:00:08 +0200 Subject: [PATCH 051/233] Feature: Add API to show/hide GUI elements (#4705) * Add API to show/hide GUI elements * Bump version to 2.3.2 --------- Co-authored-by: Konicai <71294714+Konicai@users.noreply.github.com> --- .../geyser/api/bedrock/camera/CameraData.java | 34 +++++- .../geyser/api/bedrock/camera/GuiElement.java | 60 ++++++++++ .../geyser/impl/camera/GeyserCameraData.java | 109 +++++++++++++++++- .../geyser/session/GeyserSession.java | 7 +- gradle.properties | 2 +- 5 files changed, 203 insertions(+), 9 deletions(-) create mode 100644 api/src/main/java/org/geysermc/geyser/api/bedrock/camera/GuiElement.java 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 index 2f715fa1e..f208879d1 100644 --- 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 @@ -145,4 +145,36 @@ public interface CameraData { * @return whether the camera is currently locked */ boolean isCameraLocked(); -} \ No newline at end of file + + /** + * Hides a {@link GuiElement} on the client's side. + * + * @param element the {@link GuiElement} to hide + */ + void hideElement(@NonNull GuiElement... element); + + /** + * Resets a {@link GuiElement} on the client's side. + * This makes the client decide on its own - e.g. based on client settings - + * whether to show or hide the gui element. + *

+ * If no elements are specified, this will reset all currently hidden elements + * + * @param element the {@link GuiElement} to reset + */ + void resetElement(@NonNull GuiElement @Nullable... element); + + /** + * Determines whether a {@link GuiElement} is currently hidden. + * + * @param element the {@link GuiElement} to check + */ + boolean isHudElementHidden(@NonNull GuiElement element); + + /** + * Returns the currently hidden {@link GuiElement}s. + * + * @return an unmodifiable view of all currently hidden {@link GuiElement}s + */ + @NonNull Set hiddenElements(); +} diff --git a/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/GuiElement.java b/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/GuiElement.java new file mode 100644 index 000000000..4d3653648 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/bedrock/camera/GuiElement.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 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.bedrock.camera; + +/** + * Represent GUI elements on the players HUD display. + * These can be hidden using {@link CameraData#hideElement(GuiElement...)}, + * and one can reset their visibility using {@link CameraData#resetElement(GuiElement...)}. + */ +public class GuiElement { + public static final GuiElement PAPER_DOLL = new GuiElement(0); + public static final GuiElement ARMOR = new GuiElement(1); + public static final GuiElement TOOL_TIPS = new GuiElement(2); + public static final GuiElement TOUCH_CONTROLS = new GuiElement(3); + public static final GuiElement CROSSHAIR = new GuiElement(4); + public static final GuiElement HOTBAR = new GuiElement(5); + public static final GuiElement HEALTH = new GuiElement(6); + public static final GuiElement PROGRESS_BAR = new GuiElement(7); + public static final GuiElement FOOD_BAR = new GuiElement(8); + public static final GuiElement AIR_BUBBLES_BAR = new GuiElement(9); + public static final GuiElement VEHICLE_HEALTH = new GuiElement(10); + public static final GuiElement EFFECTS_BAR = new GuiElement(11); + public static final GuiElement ITEM_TEXT_POPUP = new GuiElement(12); + + private GuiElement(int id) { + this.id = id; + } + + private final int id; + + /** + * Internal use only; don't depend on these values being consistent. + */ + public int id() { + return this.id; + } +} 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 2a93c89e3..7582502b3 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 @@ -32,24 +32,50 @@ 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.HudElement; +import org.cloudburstmc.protocol.bedrock.data.HudVisibility; 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.*; +import org.cloudburstmc.protocol.bedrock.packet.SetHudPacket; +import org.geysermc.geyser.api.bedrock.camera.CameraData; +import org.geysermc.geyser.api.bedrock.camera.CameraEaseType; +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.GuiElement; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; -import java.util.*; +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 static final HudElement[] HUD_ELEMENT_VALUES = HudElement.values(); + private static final Set ALL_HUD_ELEMENTS = Set.of(HUD_ELEMENT_VALUES); + + /** + * An array of elements to hide when the player is in spectator mode. + * Helps with tidying up the GUI; Java-style. + */ + private static final GuiElement[] SPECTATOR_HIDDEN_ELEMENTS = { + GuiElement.AIR_BUBBLES_BAR, + GuiElement.ARMOR, + GuiElement.HEALTH, + GuiElement.FOOD_BAR, + GuiElement.PROGRESS_BAR, + GuiElement.TOOL_TIPS + }; private final GeyserSession session; - @Getter - private CameraPerspective cameraPerspective; - /** * All fog effects that are currently applied to the client. */ @@ -57,6 +83,14 @@ public class GeyserCameraData implements CameraData { private final Set cameraLockOwners = new HashSet<>(); + /** + * All currently hidden HUD elements + */ + private final Set hiddenHudElements = new HashSet<>(); + + @Getter + private CameraPerspective cameraPerspective; + public GeyserCameraData(GeyserSession session) { this.session = session; } @@ -223,4 +257,67 @@ public class GeyserCameraData implements CameraData { public boolean isCameraLocked() { return !this.cameraLockOwners.isEmpty(); } -} \ No newline at end of file + + @Override + public void hideElement(GuiElement... elements) { + Objects.requireNonNull(elements); + SetHudPacket packet = new SetHudPacket(); + packet.setVisibility(HudVisibility.HIDE); + Set elementSet = packet.getElements(); + + for (GuiElement element : elements) { + this.hiddenHudElements.add(element); + elementSet.add(HUD_ELEMENT_VALUES[element.id()]); + } + + session.sendUpstreamPacket(packet); + } + + @Override + public void resetElement(GuiElement... elements) { + SetHudPacket packet = new SetHudPacket(); + packet.setVisibility(HudVisibility.RESET); + Set elementSet = packet.getElements(); + + if (elements != null && elements.length != 0) { + for (GuiElement element : elements) { + this.hiddenHudElements.remove(element); + elementSet.add(HUD_ELEMENT_VALUES[element.id()]); + } + } else { + this.hiddenHudElements.clear(); + elementSet.addAll(ALL_HUD_ELEMENTS); + } + + session.sendUpstreamPacket(packet); + } + + @Override + public boolean isHudElementHidden(@NonNull GuiElement element) { + Objects.requireNonNull(element); + return this.hiddenHudElements.contains(element); + } + + @Override + public @NonNull Set hiddenElements() { + return Collections.unmodifiableSet(hiddenHudElements); + } + + /** + * Deals with hiding hud elements while in spectator. + * + * @param currentlySpectator whether the player is currently in spectator mode + * @param newGameMode the new GameMode to switch to + */ + public void handleGameModeChange(boolean currentlySpectator, GameMode newGameMode) { + if (newGameMode == GameMode.SPECTATOR) { + if (!currentlySpectator) { + hideElement(SPECTATOR_HIDDEN_ELEMENTS); + } + } else { + if (currentlySpectator) { + resetElement(SPECTATOR_HIDDEN_ELEMENTS); + } + } + } +} 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 17010e966..fc000b95f 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -284,7 +284,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { */ private volatile boolean closed; - @Setter private GameMode gameMode = GameMode.SURVIVAL; /** @@ -1302,6 +1301,12 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { } } + public void setGameMode(GameMode newGamemode) { + boolean currentlySpectator = this.gameMode == GameMode.SPECTATOR; + this.gameMode = newGamemode; + this.cameraData.handleGameModeChange(currentlySpectator, newGamemode); + } + /** * Checks to see if a shield is in either hand to activate blocking. If so, it sets the Bedrock client to display * blocking and sends a packet to the Java server. diff --git a/gradle.properties b/gradle.properties index 40d8a36db..ea473906a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,5 +7,5 @@ org.gradle.vfs.watch=false group=org.geysermc id=geyser -version=2.3.1-SNAPSHOT +version=2.3.2-SNAPSHOT description=Allows for players from Minecraft: Bedrock Edition to join Minecraft: Java Edition servers. From 6c245a66e250bee57b98b5b3b07c08da44ea2afa Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Mon, 3 Jun 2024 23:43:35 -0400 Subject: [PATCH 052/233] Adapt for new enchantment changes --- .../living/animal/tameable/WolfEntity.java | 4 +- .../geyser/inventory/GeyserEnchantOption.java | 25 +- ...chantment.java => BedrockEnchantment.java} | 49 +--- .../updater/AnvilInventoryUpdater.java | 52 ++--- .../geyser/item/enchantment/Enchantment.java | 90 ++++++++ .../enchantment/EnchantmentComponent.java | 33 +++ .../geyser/item/type/EnchantedBookItem.java | 6 +- .../org/geysermc/geyser/item/type/Item.java | 36 ++- .../geysermc/geyser/registry/Registries.java | 25 +- .../loader/EnchantmentRegistryLoader.java | 86 ------- .../geyser/registry/type/EnchantmentData.java | 2 +- .../geyser/session/GeyserSession.java | 2 +- .../geyser/session/cache/RegistryCache.java | 2 +- .../geyser/session/cache/TagCache.java | 83 ++++--- .../geyser/session/cache/tags/BlockTag.java | 214 ++++++++++++++++-- .../session/cache/tags/EnchantmentTag.java | 89 ++++++++ .../geyser/session/cache/tags/ItemTag.java | 198 +++++++++++++--- .../EnchantingInventoryTranslator.java | 11 +- .../protocol/java/JavaCommandsTranslator.java | 23 +- .../org/geysermc/geyser/util/BlockUtils.java | 14 +- .../org/geysermc/geyser/util/ItemUtils.java | 45 +++- .../Enchantment.java => util/Ordered.java} | 22 +- core/src/main/resources/mappings | 2 +- 23 files changed, 775 insertions(+), 338 deletions(-) rename core/src/main/java/org/geysermc/geyser/inventory/item/{Enchantment.java => BedrockEnchantment.java} (69%) create mode 100644 core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java create mode 100644 core/src/main/java/org/geysermc/geyser/item/enchantment/EnchantmentComponent.java delete mode 100644 core/src/main/java/org/geysermc/geyser/registry/loader/EnchantmentRegistryLoader.java create mode 100644 core/src/main/java/org/geysermc/geyser/session/cache/tags/EnchantmentTag.java rename core/src/main/java/org/geysermc/geyser/{item/Enchantment.java => util/Ordered.java} (55%) 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 c6b8051e7..9c6c5e08d 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,8 +33,8 @@ 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.enchantment.EnchantmentComponent; import org.geysermc.geyser.item.type.DyeItem; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; @@ -123,7 +123,7 @@ public class WolfEntity extends TameableEntity { @Override public void setChestplate(ItemStack stack) { super.setChestplate(stack); - isCurseOfBinding = ItemUtils.getEnchantmentLevel(stack.getDataComponents(), Enchantment.JavaEnchantment.BINDING_CURSE) > 0; + isCurseOfBinding = ItemUtils.hasEffect(session, stack.getDataComponents(), EnchantmentComponent.PREVENT_ARMOR_CHANGE); // TODO test } @Override 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 23365e392..de0bd7300 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/GeyserEnchantOption.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/GeyserEnchantOption.java @@ -25,12 +25,11 @@ package org.geysermc.geyser.inventory; +import lombok.Getter; import org.cloudburstmc.protocol.bedrock.data.inventory.EnchantData; import org.cloudburstmc.protocol.bedrock.data.inventory.EnchantOptionData; -import lombok.Getter; import org.geysermc.geyser.session.GeyserSession; -import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -44,13 +43,13 @@ public class GeyserEnchantOption { * is controlled by the server. * So, of course, we have to throw in some easter eggs. ;) */ - private static final List ENCHANT_NAMES = Arrays.asList("tougher armor", "lukeeey", "fall better", - "explode less", "camo toy", "breathe better", "rtm five one six", "armor stab", "water walk", "you are elsa", - "tim two zero three", "fast walk nether", "davchoo", "oof ouch owie", "enemy on fire", "spider sad", "aj ferguson", "redned", - "more items thx", "long sword reach", "fast tool", "give me block", "less breaky break", "cube craft", - "strong arrow", "fist arrow", "spicy arrow", "many many arrows", "geyser", "come here fish", "i like this", - "stabby stab", "supreme mortal", "avatar i guess", "more arrows", "fly finder seventeen", "in and out", - "xp heals tools", "dragon proxy waz here"); + private static final List ENCHANT_NAMES = List.of("tougher armor", "lukeeey", "fall better", + "explode less", "camo toy", "armor stab", "breathe better", "water walk", "rtm five one six", "oof ouch owie", + "enemy on fire", "spider sad", "aj ferguson", "redned", "more items thx", "fast tool", "give me block", + "less breaky break", "cube craft", "strong arrow", "fist arrow", "spicy arrow", "many many arrows", "geyser", + "come here fish", "you are elsa", "xp heals tools", "tim two zero three", "dragon proxy waz here", + "stabby stab", "supreme mortal", "i like this", "avatar i guess", "more arrows", "in and out", + "fly finder seventeen", "fast walk nether", "davchoo", "onechris", "death bringer thirteen", "kastle"); @Getter private final int javaIndex; @@ -62,7 +61,6 @@ public class GeyserEnchantOption { private boolean hasChanged; private int xpCost = 0; - private int javaEnchantIndex = -1; private int bedrockEnchantIndex = -1; private int enchantLevel = -1; @@ -74,7 +72,7 @@ public class GeyserEnchantOption { this.hasChanged = false; return new EnchantOptionData(xpCost, javaIndex + 16, EMPTY, enchantLevel == -1 ? EMPTY : Collections.singletonList(new EnchantData(bedrockEnchantIndex, enchantLevel)), EMPTY, - javaEnchantIndex == -1 ? "unknown" : ENCHANT_NAMES.get(javaEnchantIndex), enchantLevel == -1 ? 0 : session.getNextItemNetId()); + bedrockEnchantIndex == -1 ? "unknown" : ENCHANT_NAMES.get(bedrockEnchantIndex), enchantLevel == -1 ? 0 : session.getNextItemNetId()); } public boolean hasChanged() { @@ -88,10 +86,9 @@ public class GeyserEnchantOption { } } - public void setEnchantIndex(int javaEnchantIndex, int bedrockEnchantIndex) { - if (this.javaEnchantIndex != javaEnchantIndex) { + public void setEnchantIndex(int bedrockEnchantIndex) { + if (this.bedrockEnchantIndex != bedrockEnchantIndex) { hasChanged = true; - this.javaEnchantIndex = javaEnchantIndex; this.bedrockEnchantIndex = bedrockEnchantIndex; } } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/Enchantment.java b/core/src/main/java/org/geysermc/geyser/inventory/item/BedrockEnchantment.java similarity index 69% rename from core/src/main/java/org/geysermc/geyser/inventory/item/Enchantment.java rename to core/src/main/java/org/geysermc/geyser/inventory/item/BedrockEnchantment.java index 773de29b1..a9125421e 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/Enchantment.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/BedrockEnchantment.java @@ -25,13 +25,11 @@ package org.geysermc.geyser.inventory.item; -import lombok.Getter; import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Locale; -@Getter -public enum Enchantment { +public enum BedrockEnchantment { PROTECTION, FIRE_PROTECTION, FEATHER_FALLING, @@ -69,18 +67,21 @@ public enum Enchantment { PIERCING, QUICK_CHARGE, SOUL_SPEED, - SWIFT_SNEAK; + SWIFT_SNEAK, + WIND_BURST, + DENSITY, + BREACH; - private static final Enchantment[] VALUES = values(); + private static final BedrockEnchantment[] VALUES = values(); private final String javaIdentifier; - Enchantment() { + BedrockEnchantment() { this.javaIdentifier = "minecraft:" + this.name().toLowerCase(Locale.ENGLISH); } - public static @Nullable Enchantment getByJavaIdentifier(String javaIdentifier) { - for (Enchantment enchantment : VALUES) { + public static @Nullable BedrockEnchantment getByJavaIdentifier(String javaIdentifier) { + for (BedrockEnchantment enchantment : VALUES) { if (enchantment.javaIdentifier.equals(javaIdentifier) || enchantment.name().toLowerCase(Locale.ENGLISH).equalsIgnoreCase(javaIdentifier)) { return enchantment; } @@ -88,7 +89,7 @@ public enum Enchantment { return null; } - public static @Nullable Enchantment getByBedrockId(int bedrockId) { + public static @Nullable BedrockEnchantment getByBedrockId(int bedrockId) { if (bedrockId >= 0 && bedrockId < VALUES.length) { return VALUES[bedrockId]; } @@ -141,35 +142,5 @@ public enum Enchantment { WIND_BURST, MENDING, VANISHING_CURSE; - - private static final JavaEnchantment[] VALUES = JavaEnchantment.values(); - - public static JavaEnchantment of(int index) { - return VALUES[index]; - } - - /** - * A list of all enchantment Java identifiers for use with command suggestions. - */ - public static final String[] ALL_JAVA_IDENTIFIERS; - - public static @Nullable JavaEnchantment getByJavaIdentifier(String javaIdentifier) { - if (!javaIdentifier.startsWith("minecraft:")) { - javaIdentifier = "minecraft:" + javaIdentifier; - } - for (int i = 0; i < ALL_JAVA_IDENTIFIERS.length; i++) { - if (ALL_JAVA_IDENTIFIERS[i].equalsIgnoreCase(javaIdentifier)) { - return VALUES[i]; - } - } - return null; - } - - static { - ALL_JAVA_IDENTIFIERS = new String[VALUES.length]; - for (int i = 0; i < ALL_JAVA_IDENTIFIERS.length; i++) { - ALL_JAVA_IDENTIFIERS[i] = "minecraft:" + VALUES[i].name().toLowerCase(Locale.ENGLISH); - } - } } } 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 d6a0d922b..c3ac73372 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,7 +26,6 @@ package org.geysermc.geyser.inventory.updater; 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; @@ -38,10 +37,9 @@ import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.AnvilContainer; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.Inventory; -import org.geysermc.geyser.inventory.item.Enchantment.JavaEnchantment; +import org.geysermc.geyser.inventory.item.BedrockEnchantment; +import org.geysermc.geyser.item.enchantment.Enchantment; import org.geysermc.geyser.item.Items; -import org.geysermc.geyser.registry.Registries; -import org.geysermc.geyser.registry.type.EnchantmentData; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.geysermc.geyser.translator.text.MessageTranslator; @@ -307,22 +305,22 @@ public class AnvilInventoryUpdater extends InventoryUpdater { */ private int calcMergeEnchantmentCost(GeyserSession session, GeyserItemStack input, GeyserItemStack material, boolean bedrock) { boolean hasCompatible = false; - Object2IntMap combinedEnchantments = getEnchantments(input); + Object2IntMap combinedEnchantments = getEnchantments(session, input); int cost = 0; - for (Object2IntMap.Entry entry : getEnchantments(material).object2IntEntrySet()) { - JavaEnchantment enchantment = entry.getKey(); - EnchantmentData data = Registries.ENCHANTMENTS.get(enchantment); - if (data == null) { - GeyserImpl.getInstance().getLogger().debug("Java enchantment not in registry: " + enchantment); - continue; - } + for (Object2IntMap.Entry entry : getEnchantments(session, material).object2IntEntrySet()) { + Enchantment enchantment = entry.getKey(); - boolean canApply = isEnchantedBook(input) || data.validItems().contains(input.getJavaId()); - for (JavaEnchantment incompatible : data.incompatibleEnchantments()) { - if (combinedEnchantments.containsKey(incompatible)) { - canApply = false; - if (!bedrock) { - cost++; + boolean canApply = isEnchantedBook(input) || session.getTagCache().is(enchantment.supportedItems(), input); + var exclusiveSet = enchantment.exclusiveSet(); + if (exclusiveSet != null) { + int[] incompatibleEnchantments = session.getTagCache().get(exclusiveSet); + for (int i : incompatibleEnchantments) { + Enchantment incompatible = session.getRegistryCache().enchantments().byId(i); + if (combinedEnchantments.containsKey(incompatible)) { + canApply = false; + if (!bedrock) { + cost++; + } } } } @@ -334,12 +332,12 @@ public class AnvilInventoryUpdater extends InventoryUpdater { newLevel++; } newLevel = Math.max(currentLevel, newLevel); - if (newLevel > data.maxLevel()) { - newLevel = data.maxLevel(); + if (newLevel > enchantment.maxLevel()) { + newLevel = enchantment.maxLevel(); } combinedEnchantments.put(enchantment, newLevel); - int rarityMultiplier = data.rarityMultiplier(); + int rarityMultiplier = enchantment.anvilCost(); if (isEnchantedBook(material) && rarityMultiplier > 1) { rarityMultiplier /= 2; } @@ -347,11 +345,11 @@ public class AnvilInventoryUpdater extends InventoryUpdater { if (newLevel > currentLevel) { hasCompatible = true; } - if (enchantment == JavaEnchantment.IMPALING) { + if (enchantment.bedrockEnchantment() == BedrockEnchantment.IMPALING) { // Multiplier is halved on Bedrock for some reason rarityMultiplier /= 2; - } else if (enchantment == JavaEnchantment.SWEEPING_EDGE) { - // Doesn't exist on Bedrock + } else if (enchantment.bedrockEnchantment() == null) { + // Whatever this is, doesn't exist on Bedrock rarityMultiplier = 0; } cost += rarityMultiplier * (newLevel - currentLevel); @@ -368,7 +366,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater { return cost; } - private Object2IntMap getEnchantments(GeyserItemStack itemStack) { + private Object2IntMap getEnchantments(GeyserSession session, GeyserItemStack itemStack) { ItemEnchantments enchantmentComponent; if (isEnchantedBook(itemStack)) { enchantmentComponent = itemStack.getComponent(DataComponentType.STORED_ENCHANTMENTS); @@ -376,9 +374,9 @@ public class AnvilInventoryUpdater extends InventoryUpdater { enchantmentComponent = itemStack.getComponent(DataComponentType.ENCHANTMENTS); } if (enchantmentComponent != null) { - Object2IntMap enchantments = new Object2IntOpenHashMap<>(); + Object2IntMap enchantments = new Object2IntOpenHashMap<>(); for (Map.Entry entry : enchantmentComponent.getEnchantments().entrySet()) { - JavaEnchantment enchantment = JavaEnchantment.of(entry.getKey()); + Enchantment enchantment = session.getRegistryCache().enchantments().byId(entry.getKey()); if (enchantment == null) { GeyserImpl.getInstance().getLogger().debug("Unknown Java enchantment in anvil: " + entry.getKey()); continue; diff --git a/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java b/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java new file mode 100644 index 000000000..41cc36894 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 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.enchantment; + +import org.checkerframework.checker.nullness.qual.Nullable; +import org.cloudburstmc.nbt.NbtMap; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.inventory.item.BedrockEnchantment; +import org.geysermc.geyser.session.cache.tags.EnchantmentTag; +import org.geysermc.geyser.session.cache.tags.ItemTag; +import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; + +import java.util.*; + +/** + * @param description only populated if {@link #bedrockEnchantment()} is not null. + * @param anvilCost also as a rarity multiplier + */ +public record Enchantment(String identifier, + Set effects, + ItemTag supportedItems, + int maxLevel, + String description, + int anvilCost, + @Nullable EnchantmentTag exclusiveSet, + @Nullable BedrockEnchantment bedrockEnchantment) { + + // Implementation note: I have a feeling the tags can be a list of items, because in vanilla they're HolderSet classes. + // I'm not sure how that's wired over the network, so we'll put it off. + public static Enchantment read(RegistryEntry entry) { + NbtMap data = entry.getData(); + Set effects = readEnchantmentComponents(data.getCompound("effects")); + String supportedItems = data.getString("supported_items").substring(1); // Remove '#' at beginning that indicates tag + int maxLevel = data.getInt("max_level"); + int anvilCost = data.getInt("anvil_cost"); + String exclusiveSet = data.getString("exclusive_set", null); + EnchantmentTag exclusiveSetTag = exclusiveSet == null ? null : EnchantmentTag.ALL_ENCHANTMENT_TAGS.get(exclusiveSet.substring(1)); + BedrockEnchantment bedrockEnchantment = BedrockEnchantment.getByJavaIdentifier(entry.getId()); + String description = bedrockEnchantment == null ? readDescription(data) : null; + + return new Enchantment(entry.getId(), effects, ItemTag.ALL_ITEM_TAGS.get(supportedItems), maxLevel, + description, anvilCost, exclusiveSetTag, bedrockEnchantment); + } + + private static Set readEnchantmentComponents(NbtMap effects) { + if (effects.isEmpty()) { + return Collections.emptySet(); + } + Set components = new HashSet<>(); + for (Map.Entry entry : effects.entrySet()) { + switch (entry.getKey()) { + case "minecraft:prevent_armor_change" -> components.add(EnchantmentComponent.PREVENT_ARMOR_CHANGE); + } + } + return components; + } + + private static String readDescription(NbtMap tag) { + NbtMap description = tag.getCompound("description"); + String translate = description.getString("translate", null); + if (translate == null) { + GeyserImpl.getInstance().getLogger().debug("Don't know how to read description! " + tag); + return ""; + } + return translate; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/item/enchantment/EnchantmentComponent.java b/core/src/main/java/org/geysermc/geyser/item/enchantment/EnchantmentComponent.java new file mode 100644 index 000000000..66d110f98 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/item/enchantment/EnchantmentComponent.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 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.enchantment; + +public class EnchantmentComponent { + /** + * Singleton with no additional data + */ + public static final EnchantmentComponent PREVENT_ARMOR_CHANGE = new EnchantmentComponent(); +} 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 98e98b4b8..540270555 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 @@ -31,7 +31,7 @@ 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.inventory.item.BedrockEnchantment; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; @@ -78,11 +78,11 @@ public class EnchantedBookItem extends Item { for (NbtMap bedrockEnchantment : enchantmentTag) { short bedrockId = bedrockEnchantment.getShort("id"); - Enchantment enchantment = Enchantment.getByBedrockId(bedrockId); + BedrockEnchantment enchantment = BedrockEnchantment.getByBedrockId(bedrockId); if (enchantment != null) { int level = bedrockEnchantment.getShort("lvl", (short) 1); // TODO - javaEnchantments.put(Enchantment.JavaEnchantment.valueOf(enchantment.name()).ordinal(), level); + //javaEnchantments.put(BedrockEnchantment.JavaEnchantment.valueOf(enchantment.name()).ordinal(), level); } else { GeyserImpl.getInstance().getLogger().debug("Unknown bedrock enchantment: " + bedrockId); } 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 1ec410eaf..8c67d7d5f 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 @@ -33,8 +33,9 @@ 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.inventory.item.BedrockEnchantment; import org.geysermc.geyser.item.Items; +import org.geysermc.geyser.item.enchantment.Enchantment; import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; @@ -201,7 +202,7 @@ public class Item { // ShortTag bedrockId = tagValue.get("id"); // if (bedrockId == null) continue; // -// Enchantment enchantment = Enchantment.getByBedrockId(bedrockId.getValue()); +// BedrockEnchantment enchantment = BedrockEnchantment.getByBedrockId(bedrockId.getValue()); // if (enchantment != null) { // CompoundTag javaTag = new CompoundTag(""); // Map javaValue = javaTag.getValue(); @@ -226,33 +227,22 @@ public class Item { // } } - /** - * This is a map from Java-only enchantments to their translation keys so that we can - * map these enchantments to Bedrock clients, since they don't actually exist there. - */ - private static final Map ENCHANTMENT_TRANSLATION_KEYS = Map.of( - Enchantment.JavaEnchantment.SWEEPING_EDGE, "enchantment.minecraft.sweeping", - Enchantment.JavaEnchantment.DENSITY, "enchantment.minecraft.density", - Enchantment.JavaEnchantment.BREACH, "enchantment.minecraft.breach", - Enchantment.JavaEnchantment.WIND_BURST, "enchantment.minecraft.wind_burst"); - 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); - String translationKey = ENCHANTMENT_TRANSLATION_KEYS.get(enchantment); - if (translationKey != null) { - String enchantmentTranslation = MinecraftLocale.getLocaleString(translationKey, session.locale()); - addJavaOnlyEnchantment(session, builder, enchantmentTranslation, level); - return null; - } + Enchantment enchantment = session.getRegistryCache().enchantments().byId(enchantId); if (enchantment == null) { GeyserImpl.getInstance().getLogger().debug("Unknown Java enchantment while NBT item translating: " + enchantId); return null; } + BedrockEnchantment bedrockEnchantment = enchantment.bedrockEnchantment(); + if (bedrockEnchantment == null) { + String enchantmentTranslation = MinecraftLocale.getLocaleString(enchantment.description(), session.locale()); + addJavaOnlyEnchantment(session, builder, enchantmentTranslation, level); + return null; + } + return NbtMap.builder() - .putShort("id", (short) Enchantment.valueOf(enchantment.name()).ordinal()) + .putShort("id", (short) bedrockEnchantment.ordinal()) .putShort("lvl", (short) level) .build(); } @@ -260,7 +250,7 @@ public class Item { private void addJavaOnlyEnchantment(GeyserSession session, BedrockItemBuilder builder, String enchantmentName, int level) { String lvlTranslation = MinecraftLocale.getLocaleString("enchantment.level." + level, session.locale()); - builder.getOrCreateLore().add(ChatColor.RESET + ChatColor.GRAY + enchantmentName + " " + lvlTranslation); + builder.getOrCreateLore().add(0, ChatColor.RESET + ChatColor.GRAY + enchantmentName + " " + lvlTranslation); } /* Translation methods end */ 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 54d013140..c6980efd1 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,6 @@ package org.geysermc.geyser.registry; -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; @@ -43,7 +37,6 @@ 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; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.registry.loader.*; @@ -51,7 +44,6 @@ import org.geysermc.geyser.registry.populator.ItemRegistryPopulator; import org.geysermc.geyser.registry.populator.PacketRegistryPopulator; import org.geysermc.geyser.registry.populator.RecipeRegistryPopulator; import org.geysermc.geyser.registry.provider.ProviderSupplier; -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; @@ -59,6 +51,12 @@ import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator; import org.geysermc.geyser.translator.level.event.LevelEventTranslator; import org.geysermc.geyser.translator.sound.SoundInteractionTranslator; import org.geysermc.geyser.translator.sound.SoundTranslator; +import org.geysermc.mcprotocollib.network.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 java.util.*; @@ -102,11 +100,6 @@ public final class Registries { */ public static final VersionedRegistry>> CRAFTING_DATA = VersionedRegistry.create(RegistryLoaders.empty(Int2ObjectOpenHashMap::new)); - /** - * A registry holding data of all the known enchantments. - */ - public static final SimpleMappedRegistry ENCHANTMENTS; - /** * A map containing all entity types and their respective Geyser definitions */ @@ -127,7 +120,10 @@ public final class Registries { */ public static final PacketTranslatorRegistry JAVA_PACKET_TRANSLATORS = PacketTranslatorRegistry.create(); - public static final SimpleRegistry> JAVA_ITEMS = SimpleRegistry.create(RegistryLoaders.empty(ArrayList::new)); + /** + * A registry containing all Java items ordered by their network ID. + */ + public static final ListRegistry JAVA_ITEMS = ListRegistry.create(RegistryLoaders.empty(ArrayList::new)); public static final SimpleMappedRegistry JAVA_ITEM_IDENTIFIERS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new)); @@ -190,7 +186,6 @@ public final class Registries { // Create registries that require other registries to load first POTION_MIXES = VersionedRegistry.create(PotionMixRegistryLoader::new); - ENCHANTMENTS = SimpleMappedRegistry.create("mappings/enchantments.json", EnchantmentRegistryLoader::new); // Remove unneeded client generation data from NbtMapBuilder NbtMapBuilder biomesNbt = NbtMap.builder(); 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 deleted file mode 100644 index 8a0fb1f40..000000000 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/EnchantmentRegistryLoader.java +++ /dev/null @@ -1,86 +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.registry.loader; - -import com.fasterxml.jackson.databind.JsonNode; -import it.unimi.dsi.fastutil.ints.IntOpenHashSet; -import it.unimi.dsi.fastutil.ints.IntSet; -import org.geysermc.geyser.GeyserImpl; -import org.geysermc.geyser.inventory.item.Enchantment.JavaEnchantment; -import org.geysermc.geyser.item.type.Item; -import org.geysermc.geyser.registry.Registries; -import org.geysermc.geyser.registry.type.EnchantmentData; - -import java.io.InputStream; -import java.util.EnumMap; -import java.util.EnumSet; -import java.util.Iterator; -import java.util.Map; - -public class EnchantmentRegistryLoader implements RegistryLoader> { - @Override - public Map load(String input) { - JsonNode enchantmentsNode; - 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); - } - - Map enchantments = new EnumMap<>(JavaEnchantment.class); - Iterator> it = enchantmentsNode.fields(); - while (it.hasNext()) { - Map.Entry entry = it.next(); - JavaEnchantment key = JavaEnchantment.getByJavaIdentifier(entry.getKey()); - JsonNode node = entry.getValue(); - int rarityMultiplier = node.get("anvil_cost").asInt(); - int maxLevel = node.get("max_level").asInt(); - - EnumSet incompatibleEnchantments = EnumSet.noneOf(JavaEnchantment.class); - JsonNode incompatibleEnchantmentsNode = node.get("incompatible_enchantments"); - if (incompatibleEnchantmentsNode != null) { - for (JsonNode incompatibleNode : incompatibleEnchantmentsNode) { - incompatibleEnchantments.add(JavaEnchantment.getByJavaIdentifier(incompatibleNode.textValue())); - } - } - - IntSet validItems = new IntOpenHashSet(); - for (JsonNode itemNode : node.get("valid_items")) { - String javaIdentifier = itemNode.textValue(); - Item item = Registries.JAVA_ITEM_IDENTIFIERS.get(javaIdentifier); - if (item != null) { - validItems.add(item.javaId()); - } else { - throw new NullPointerException("No item entry exists for java identifier: " + javaIdentifier); - } - } - - EnchantmentData enchantmentData = new EnchantmentData(rarityMultiplier, maxLevel, incompatibleEnchantments, validItems); - enchantments.put(key, enchantmentData); - } - return enchantments; - } -} diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/EnchantmentData.java b/core/src/main/java/org/geysermc/geyser/registry/type/EnchantmentData.java index 970e128a4..d341cd9e3 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/type/EnchantmentData.java +++ b/core/src/main/java/org/geysermc/geyser/registry/type/EnchantmentData.java @@ -26,7 +26,7 @@ package org.geysermc.geyser.registry.type; import it.unimi.dsi.fastutil.ints.IntSet; -import org.geysermc.geyser.inventory.item.Enchantment.JavaEnchantment; +import org.geysermc.geyser.inventory.item.BedrockEnchantment.JavaEnchantment; import java.util.Set; 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 9543c7943..fc487b17e 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -1307,7 +1307,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { */ public void useItem(Hand hand) { sendDownstreamGamePacket(new ServerboundUseItemPacket( - hand, worldCache.nextPredictionSequence(), playerEntity.getPitch(), playerEntity.getYaw())); + hand, worldCache.nextPredictionSequence(), playerEntity.getYaw(), playerEntity.getPitch())); } /** 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 a9b14fdc0..fe970ee2b 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 @@ -38,7 +38,7 @@ 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.item.Enchantment; +import org.geysermc.geyser.item.enchantment.Enchantment; import org.geysermc.geyser.level.JavaDimension; import org.geysermc.geyser.level.PaintingType; import org.geysermc.geyser.session.GeyserSession; 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 95f5c1cc3..335e940f4 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,47 +25,40 @@ package org.geysermc.geyser.session.cache; -import it.unimi.dsi.fastutil.ints.IntList; +import it.unimi.dsi.fastutil.ints.IntArrays; +import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.BlockTag; +import org.geysermc.geyser.session.cache.tags.EnchantmentTag; import org.geysermc.geyser.session.cache.tags.ItemTag; +import org.geysermc.geyser.util.Ordered; import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundUpdateTagsPacket; import javax.annotation.ParametersAreNonnullByDefault; -import java.util.EnumMap; -import java.util.HashMap; +import java.util.Arrays; import java.util.Map; +import static org.geysermc.geyser.session.cache.tags.BlockTag.ALL_BLOCK_TAGS; +import static org.geysermc.geyser.session.cache.tags.EnchantmentTag.ALL_ENCHANTMENT_TAGS; +import static org.geysermc.geyser.session.cache.tags.ItemTag.ALL_ITEM_TAGS; + /** * 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 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 final Map blocks = new EnumMap<>(BlockTag.class); - private final Map items = new EnumMap<>(ItemTag.class); + private final int[][] blocks = new int[ALL_BLOCK_TAGS.size()][]; + private final int[][] items = new int[ALL_ITEM_TAGS.size()][]; + private final int[][] enchantments = new int[ALL_ENCHANTMENT_TAGS.size()][]; public void loadPacket(GeyserSession session, ClientboundUpdateTagsPacket packet) { Map blockTags = packet.getTags().get("minecraft:block"); - 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); - } - }); + loadTags("Block", blockTags, ALL_BLOCK_TAGS, this.blocks); // Hack btw GeyserLogger logger = session.getGeyser().getLogger(); @@ -77,15 +70,7 @@ public final class TagCache { } Map itemTags = packet.getTags().get("minecraft:item"); - 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); - } - }); + loadTags("Item", itemTags, ALL_ITEM_TAGS, this.items); // Hack btw boolean emulatePost1_13Logic = itemTags.get("minecraft:signs").length > 1; @@ -93,17 +78,31 @@ public final class TagCache { if (logger.isDebug()) { logger.debug("Emulating post 1.13 villager logic for " + session.bedrockUsername() + "? " + emulatePost1_13Logic); } + + Map enchantmentTags = packet.getTags().get("minecraft:enchantment"); + loadTags("Enchantment", enchantmentTags, ALL_ENCHANTMENT_TAGS, this.enchantments); + } + + private void loadTags(String type, Map packetTags, Map allTags, int[][] localValues) { + Arrays.fill(localValues, IntArrays.EMPTY_ARRAY); + allTags.forEach((location, tag) -> { + int[] values = packetTags.get(location); + if (values != null) { + if (values.length != 0) { + localValues[tag.ordinal()] = values; + } + } else { + GeyserImpl.getInstance().getLogger().debug(type + " tag not found from server: " + location); + } + }); } /** * @return true if the block tag is present and contains this block mapping's Java ID. */ public boolean is(BlockTag tag, Block block) { - IntList values = this.blocks.get(tag); - if (values != null) { - return values.contains(block.javaId()); - } - return false; + int[] values = this.blocks[tag.ordinal()]; + return contains(values, block.javaId()); } /** @@ -117,9 +116,19 @@ public final class TagCache { * @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()); + int[] values = this.items[tag.ordinal()]; + return contains(values, item.javaId()); + } + + public int[] get(EnchantmentTag tag) { + return this.enchantments[tag.ordinal()]; + } + + private static boolean contains(int[] array, int i) { + for (int item : array) { + if (item == i) { + return true; + } } 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 index 7017ad55c..32d708eca 100644 --- 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 @@ -25,24 +25,212 @@ package org.geysermc.geyser.session.cache.tags; -import org.geysermc.geyser.session.cache.TagCache; +import org.geysermc.geyser.util.Ordered; -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"); +import java.util.HashMap; +import java.util.Map; + +@SuppressWarnings("unused") +public final class BlockTag implements Ordered { + public static final Map ALL_BLOCK_TAGS = new HashMap<>(); + + public static final BlockTag WOOL = new BlockTag("wool"); + public static final BlockTag PLANKS = new BlockTag("planks"); + public static final BlockTag STONE_BRICKS = new BlockTag("stone_bricks"); + public static final BlockTag WOODEN_BUTTONS = new BlockTag("wooden_buttons"); + public static final BlockTag STONE_BUTTONS = new BlockTag("stone_buttons"); + public static final BlockTag BUTTONS = new BlockTag("buttons"); + public static final BlockTag WOOL_CARPETS = new BlockTag("wool_carpets"); + public static final BlockTag WOODEN_DOORS = new BlockTag("wooden_doors"); + public static final BlockTag WOODEN_STAIRS = new BlockTag("wooden_stairs"); + public static final BlockTag WOODEN_SLABS = new BlockTag("wooden_slabs"); + public static final BlockTag WOODEN_FENCES = new BlockTag("wooden_fences"); + public static final BlockTag PRESSURE_PLATES = new BlockTag("pressure_plates"); + public static final BlockTag WOODEN_PRESSURE_PLATES = new BlockTag("wooden_pressure_plates"); + public static final BlockTag STONE_PRESSURE_PLATES = new BlockTag("stone_pressure_plates"); + public static final BlockTag WOODEN_TRAPDOORS = new BlockTag("wooden_trapdoors"); + public static final BlockTag DOORS = new BlockTag("doors"); + public static final BlockTag SAPLINGS = new BlockTag("saplings"); + public static final BlockTag LOGS_THAT_BURN = new BlockTag("logs_that_burn"); + public static final BlockTag OVERWORLD_NATURAL_LOGS = new BlockTag("overworld_natural_logs"); + public static final BlockTag LOGS = new BlockTag("logs"); + public static final BlockTag DARK_OAK_LOGS = new BlockTag("dark_oak_logs"); + public static final BlockTag OAK_LOGS = new BlockTag("oak_logs"); + public static final BlockTag BIRCH_LOGS = new BlockTag("birch_logs"); + public static final BlockTag ACACIA_LOGS = new BlockTag("acacia_logs"); + public static final BlockTag CHERRY_LOGS = new BlockTag("cherry_logs"); + public static final BlockTag JUNGLE_LOGS = new BlockTag("jungle_logs"); + public static final BlockTag SPRUCE_LOGS = new BlockTag("spruce_logs"); + public static final BlockTag MANGROVE_LOGS = new BlockTag("mangrove_logs"); + public static final BlockTag CRIMSON_STEMS = new BlockTag("crimson_stems"); + public static final BlockTag WARPED_STEMS = new BlockTag("warped_stems"); + public static final BlockTag BAMBOO_BLOCKS = new BlockTag("bamboo_blocks"); + public static final BlockTag WART_BLOCKS = new BlockTag("wart_blocks"); + public static final BlockTag BANNERS = new BlockTag("banners"); + public static final BlockTag SAND = new BlockTag("sand"); + public static final BlockTag SMELTS_TO_GLASS = new BlockTag("smelts_to_glass"); + public static final BlockTag STAIRS = new BlockTag("stairs"); + public static final BlockTag SLABS = new BlockTag("slabs"); + public static final BlockTag WALLS = new BlockTag("walls"); + public static final BlockTag ANVIL = new BlockTag("anvil"); + public static final BlockTag RAILS = new BlockTag("rails"); + public static final BlockTag LEAVES = new BlockTag("leaves"); + public static final BlockTag TRAPDOORS = new BlockTag("trapdoors"); + public static final BlockTag SMALL_FLOWERS = new BlockTag("small_flowers"); + public static final BlockTag BEDS = new BlockTag("beds"); + public static final BlockTag FENCES = new BlockTag("fences"); + public static final BlockTag TALL_FLOWERS = new BlockTag("tall_flowers"); + public static final BlockTag FLOWERS = new BlockTag("flowers"); + public static final BlockTag PIGLIN_REPELLENTS = new BlockTag("piglin_repellents"); + public static final BlockTag GOLD_ORES = new BlockTag("gold_ores"); + public static final BlockTag IRON_ORES = new BlockTag("iron_ores"); + public static final BlockTag DIAMOND_ORES = new BlockTag("diamond_ores"); + public static final BlockTag REDSTONE_ORES = new BlockTag("redstone_ores"); + public static final BlockTag LAPIS_ORES = new BlockTag("lapis_ores"); + public static final BlockTag COAL_ORES = new BlockTag("coal_ores"); + public static final BlockTag EMERALD_ORES = new BlockTag("emerald_ores"); + public static final BlockTag COPPER_ORES = new BlockTag("copper_ores"); + public static final BlockTag CANDLES = new BlockTag("candles"); + public static final BlockTag DIRT = new BlockTag("dirt"); + public static final BlockTag TERRACOTTA = new BlockTag("terracotta"); + public static final BlockTag BADLANDS_TERRACOTTA = new BlockTag("badlands_terracotta"); + public static final BlockTag CONCRETE_POWDER = new BlockTag("concrete_powder"); + public static final BlockTag COMPLETES_FIND_TREE_TUTORIAL = new BlockTag("completes_find_tree_tutorial"); + public static final BlockTag FLOWER_POTS = new BlockTag("flower_pots"); + public static final BlockTag ENDERMAN_HOLDABLE = new BlockTag("enderman_holdable"); + public static final BlockTag ICE = new BlockTag("ice"); + public static final BlockTag VALID_SPAWN = new BlockTag("valid_spawn"); + public static final BlockTag IMPERMEABLE = new BlockTag("impermeable"); + public static final BlockTag UNDERWATER_BONEMEALS = new BlockTag("underwater_bonemeals"); + public static final BlockTag CORAL_BLOCKS = new BlockTag("coral_blocks"); + public static final BlockTag WALL_CORALS = new BlockTag("wall_corals"); + public static final BlockTag CORAL_PLANTS = new BlockTag("coral_plants"); + public static final BlockTag CORALS = new BlockTag("corals"); + public static final BlockTag BAMBOO_PLANTABLE_ON = new BlockTag("bamboo_plantable_on"); + public static final BlockTag STANDING_SIGNS = new BlockTag("standing_signs"); + public static final BlockTag WALL_SIGNS = new BlockTag("wall_signs"); + public static final BlockTag SIGNS = new BlockTag("signs"); + public static final BlockTag CEILING_HANGING_SIGNS = new BlockTag("ceiling_hanging_signs"); + public static final BlockTag WALL_HANGING_SIGNS = new BlockTag("wall_hanging_signs"); + public static final BlockTag ALL_HANGING_SIGNS = new BlockTag("all_hanging_signs"); + public static final BlockTag ALL_SIGNS = new BlockTag("all_signs"); + public static final BlockTag DRAGON_IMMUNE = new BlockTag("dragon_immune"); + public static final BlockTag DRAGON_TRANSPARENT = new BlockTag("dragon_transparent"); + public static final BlockTag WITHER_IMMUNE = new BlockTag("wither_immune"); + public static final BlockTag WITHER_SUMMON_BASE_BLOCKS = new BlockTag("wither_summon_base_blocks"); + public static final BlockTag BEEHIVES = new BlockTag("beehives"); + public static final BlockTag CROPS = new BlockTag("crops"); + public static final BlockTag BEE_GROWABLES = new BlockTag("bee_growables"); + public static final BlockTag PORTALS = new BlockTag("portals"); + public static final BlockTag FIRE = new BlockTag("fire"); + public static final BlockTag NYLIUM = new BlockTag("nylium"); + public static final BlockTag BEACON_BASE_BLOCKS = new BlockTag("beacon_base_blocks"); + public static final BlockTag SOUL_SPEED_BLOCKS = new BlockTag("soul_speed_blocks"); + public static final BlockTag WALL_POST_OVERRIDE = new BlockTag("wall_post_override"); + public static final BlockTag CLIMBABLE = new BlockTag("climbable"); + public static final BlockTag FALL_DAMAGE_RESETTING = new BlockTag("fall_damage_resetting"); + public static final BlockTag SHULKER_BOXES = new BlockTag("shulker_boxes"); + public static final BlockTag HOGLIN_REPELLENTS = new BlockTag("hoglin_repellents"); + public static final BlockTag SOUL_FIRE_BASE_BLOCKS = new BlockTag("soul_fire_base_blocks"); + public static final BlockTag STRIDER_WARM_BLOCKS = new BlockTag("strider_warm_blocks"); + public static final BlockTag CAMPFIRES = new BlockTag("campfires"); + public static final BlockTag GUARDED_BY_PIGLINS = new BlockTag("guarded_by_piglins"); + public static final BlockTag PREVENT_MOB_SPAWNING_INSIDE = new BlockTag("prevent_mob_spawning_inside"); + public static final BlockTag FENCE_GATES = new BlockTag("fence_gates"); + public static final BlockTag UNSTABLE_BOTTOM_CENTER = new BlockTag("unstable_bottom_center"); + public static final BlockTag MUSHROOM_GROW_BLOCK = new BlockTag("mushroom_grow_block"); + public static final BlockTag INFINIBURN_OVERWORLD = new BlockTag("infiniburn_overworld"); + public static final BlockTag INFINIBURN_NETHER = new BlockTag("infiniburn_nether"); + public static final BlockTag INFINIBURN_END = new BlockTag("infiniburn_end"); + public static final BlockTag BASE_STONE_OVERWORLD = new BlockTag("base_stone_overworld"); + public static final BlockTag STONE_ORE_REPLACEABLES = new BlockTag("stone_ore_replaceables"); + public static final BlockTag DEEPSLATE_ORE_REPLACEABLES = new BlockTag("deepslate_ore_replaceables"); + public static final BlockTag BASE_STONE_NETHER = new BlockTag("base_stone_nether"); + public static final BlockTag OVERWORLD_CARVER_REPLACEABLES = new BlockTag("overworld_carver_replaceables"); + public static final BlockTag NETHER_CARVER_REPLACEABLES = new BlockTag("nether_carver_replaceables"); + public static final BlockTag CANDLE_CAKES = new BlockTag("candle_cakes"); + public static final BlockTag CAULDRONS = new BlockTag("cauldrons"); + public static final BlockTag CRYSTAL_SOUND_BLOCKS = new BlockTag("crystal_sound_blocks"); + public static final BlockTag INSIDE_STEP_SOUND_BLOCKS = new BlockTag("inside_step_sound_blocks"); + public static final BlockTag COMBINATION_STEP_SOUND_BLOCKS = new BlockTag("combination_step_sound_blocks"); + public static final BlockTag CAMEL_SAND_STEP_SOUND_BLOCKS = new BlockTag("camel_sand_step_sound_blocks"); + public static final BlockTag OCCLUDES_VIBRATION_SIGNALS = new BlockTag("occludes_vibration_signals"); + public static final BlockTag DAMPENS_VIBRATIONS = new BlockTag("dampens_vibrations"); + public static final BlockTag DRIPSTONE_REPLACEABLE_BLOCKS = new BlockTag("dripstone_replaceable_blocks"); + public static final BlockTag CAVE_VINES = new BlockTag("cave_vines"); + public static final BlockTag MOSS_REPLACEABLE = new BlockTag("moss_replaceable"); + public static final BlockTag LUSH_GROUND_REPLACEABLE = new BlockTag("lush_ground_replaceable"); + public static final BlockTag AZALEA_ROOT_REPLACEABLE = new BlockTag("azalea_root_replaceable"); + public static final BlockTag SMALL_DRIPLEAF_PLACEABLE = new BlockTag("small_dripleaf_placeable"); + public static final BlockTag BIG_DRIPLEAF_PLACEABLE = new BlockTag("big_dripleaf_placeable"); + public static final BlockTag SNOW = new BlockTag("snow"); + public static final BlockTag MINEABLE_AXE = new BlockTag("mineable/axe"); + public static final BlockTag MINEABLE_HOE = new BlockTag("mineable/hoe"); + public static final BlockTag MINEABLE_PICKAXE = new BlockTag("mineable/pickaxe"); + public static final BlockTag MINEABLE_SHOVEL = new BlockTag("mineable/shovel"); + public static final BlockTag SWORD_EFFICIENT = new BlockTag("sword_efficient"); + public static final BlockTag NEEDS_DIAMOND_TOOL = new BlockTag("needs_diamond_tool"); + public static final BlockTag NEEDS_IRON_TOOL = new BlockTag("needs_iron_tool"); + public static final BlockTag NEEDS_STONE_TOOL = new BlockTag("needs_stone_tool"); + public static final BlockTag INCORRECT_FOR_NETHERITE_TOOL = new BlockTag("incorrect_for_netherite_tool"); + public static final BlockTag INCORRECT_FOR_DIAMOND_TOOL = new BlockTag("incorrect_for_diamond_tool"); + public static final BlockTag INCORRECT_FOR_IRON_TOOL = new BlockTag("incorrect_for_iron_tool"); + public static final BlockTag INCORRECT_FOR_STONE_TOOL = new BlockTag("incorrect_for_stone_tool"); + public static final BlockTag INCORRECT_FOR_GOLD_TOOL = new BlockTag("incorrect_for_gold_tool"); + public static final BlockTag INCORRECT_FOR_WOODEN_TOOL = new BlockTag("incorrect_for_wooden_tool"); + public static final BlockTag FEATURES_CANNOT_REPLACE = new BlockTag("features_cannot_replace"); + public static final BlockTag LAVA_POOL_STONE_CANNOT_REPLACE = new BlockTag("lava_pool_stone_cannot_replace"); + public static final BlockTag GEODE_INVALID_BLOCKS = new BlockTag("geode_invalid_blocks"); + public static final BlockTag FROG_PREFER_JUMP_TO = new BlockTag("frog_prefer_jump_to"); + public static final BlockTag SCULK_REPLACEABLE = new BlockTag("sculk_replaceable"); + public static final BlockTag SCULK_REPLACEABLE_WORLD_GEN = new BlockTag("sculk_replaceable_world_gen"); + public static final BlockTag ANCIENT_CITY_REPLACEABLE = new BlockTag("ancient_city_replaceable"); + public static final BlockTag VIBRATION_RESONATORS = new BlockTag("vibration_resonators"); + public static final BlockTag ANIMALS_SPAWNABLE_ON = new BlockTag("animals_spawnable_on"); + public static final BlockTag ARMADILLO_SPAWNABLE_ON = new BlockTag("armadillo_spawnable_on"); + public static final BlockTag AXOLOTLS_SPAWNABLE_ON = new BlockTag("axolotls_spawnable_on"); + public static final BlockTag GOATS_SPAWNABLE_ON = new BlockTag("goats_spawnable_on"); + public static final BlockTag MOOSHROOMS_SPAWNABLE_ON = new BlockTag("mooshrooms_spawnable_on"); + public static final BlockTag PARROTS_SPAWNABLE_ON = new BlockTag("parrots_spawnable_on"); + public static final BlockTag POLAR_BEARS_SPAWNABLE_ON_ALTERNATE = new BlockTag("polar_bears_spawnable_on_alternate"); + public static final BlockTag RABBITS_SPAWNABLE_ON = new BlockTag("rabbits_spawnable_on"); + public static final BlockTag FOXES_SPAWNABLE_ON = new BlockTag("foxes_spawnable_on"); + public static final BlockTag WOLVES_SPAWNABLE_ON = new BlockTag("wolves_spawnable_on"); + public static final BlockTag FROGS_SPAWNABLE_ON = new BlockTag("frogs_spawnable_on"); + public static final BlockTag AZALEA_GROWS_ON = new BlockTag("azalea_grows_on"); + public static final BlockTag CONVERTABLE_TO_MUD = new BlockTag("convertable_to_mud"); + public static final BlockTag MANGROVE_LOGS_CAN_GROW_THROUGH = new BlockTag("mangrove_logs_can_grow_through"); + public static final BlockTag MANGROVE_ROOTS_CAN_GROW_THROUGH = new BlockTag("mangrove_roots_can_grow_through"); + public static final BlockTag DEAD_BUSH_MAY_PLACE_ON = new BlockTag("dead_bush_may_place_on"); + public static final BlockTag SNAPS_GOAT_HORN = new BlockTag("snaps_goat_horn"); + public static final BlockTag REPLACEABLE_BY_TREES = new BlockTag("replaceable_by_trees"); + public static final BlockTag SNOW_LAYER_CANNOT_SURVIVE_ON = new BlockTag("snow_layer_cannot_survive_on"); + public static final BlockTag SNOW_LAYER_CAN_SURVIVE_ON = new BlockTag("snow_layer_can_survive_on"); + public static final BlockTag INVALID_SPAWN_INSIDE = new BlockTag("invalid_spawn_inside"); + public static final BlockTag SNIFFER_DIGGABLE_BLOCK = new BlockTag("sniffer_diggable_block"); + public static final BlockTag SNIFFER_EGG_HATCH_BOOST = new BlockTag("sniffer_egg_hatch_boost"); + public static final BlockTag TRAIL_RUINS_REPLACEABLE = new BlockTag("trail_ruins_replaceable"); + public static final BlockTag REPLACEABLE = new BlockTag("replaceable"); + public static final BlockTag ENCHANTMENT_POWER_PROVIDER = new BlockTag("enchantment_power_provider"); + public static final BlockTag ENCHANTMENT_POWER_TRANSMITTER = new BlockTag("enchantment_power_transmitter"); + public static final BlockTag MAINTAINS_FARMLAND = new BlockTag("maintains_farmland"); + public static final BlockTag BLOCKS_WIND_CHARGE_EXPLOSIONS = new BlockTag("blocks_wind_charge_explosions"); + public static final BlockTag DOES_NOT_BLOCK_HOPPERS = new BlockTag("does_not_block_hoppers"); + public static final BlockTag AIR = new BlockTag("air"); + + private final int id; - BlockTag(String identifier) { + private BlockTag(String identifier) { + this.id = ALL_BLOCK_TAGS.size(); register(identifier, this); } + @Override + public int ordinal() { + return id; + } + private static void register(String name, BlockTag tag) { - TagCache.ALL_BLOCK_TAGS.put("minecraft:" + name, tag); + ALL_BLOCK_TAGS.put(("minecraft:" + name).intern(), tag); } } diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/tags/EnchantmentTag.java b/core/src/main/java/org/geysermc/geyser/session/cache/tags/EnchantmentTag.java new file mode 100644 index 000000000..3c5446adc --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/session/cache/tags/EnchantmentTag.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 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.util.Ordered; + +import java.util.HashMap; +import java.util.Map; + +@SuppressWarnings("unused") +public final class EnchantmentTag implements Ordered { + public static final Map ALL_ENCHANTMENT_TAGS = new HashMap<>(); + + public static final EnchantmentTag TOOLTIP_ORDER = new EnchantmentTag("tooltip_order"); + public static final EnchantmentTag EXCLUSIVE_SET_ARMOR = new EnchantmentTag("exclusive_set/armor"); + public static final EnchantmentTag EXCLUSIVE_SET_BOOTS = new EnchantmentTag("exclusive_set/boots"); + public static final EnchantmentTag EXCLUSIVE_SET_BOW = new EnchantmentTag("exclusive_set/bow"); + public static final EnchantmentTag EXCLUSIVE_SET_CROSSBOW = new EnchantmentTag("exclusive_set/crossbow"); + public static final EnchantmentTag EXCLUSIVE_SET_DAMAGE = new EnchantmentTag("exclusive_set/damage"); + public static final EnchantmentTag EXCLUSIVE_SET_MINING = new EnchantmentTag("exclusive_set/mining"); + public static final EnchantmentTag EXCLUSIVE_SET_RIPTIDE = new EnchantmentTag("exclusive_set/riptide"); + public static final EnchantmentTag TRADEABLE = new EnchantmentTag("tradeable"); + public static final EnchantmentTag DOUBLE_TRADE_PRICE = new EnchantmentTag("double_trade_price"); + public static final EnchantmentTag IN_ENCHANTING_TABLE = new EnchantmentTag("in_enchanting_table"); + public static final EnchantmentTag ON_MOB_SPAWN_EQUIPMENT = new EnchantmentTag("on_mob_spawn_equipment"); + public static final EnchantmentTag ON_TRADED_EQUIPMENT = new EnchantmentTag("on_traded_equipment"); + public static final EnchantmentTag ON_RANDOM_LOOT = new EnchantmentTag("on_random_loot"); + public static final EnchantmentTag CURSE = new EnchantmentTag("curse"); + public static final EnchantmentTag SMELTS_LOOT = new EnchantmentTag("smelts_loot"); + public static final EnchantmentTag PREVENTS_BEE_SPAWNS_WHEN_MINING = new EnchantmentTag("prevents_bee_spawns_when_mining"); + public static final EnchantmentTag PREVENTS_DECORATED_POT_SHATTERING = new EnchantmentTag("prevents_decorated_pot_shattering"); + public static final EnchantmentTag PREVENTS_ICE_MELTING = new EnchantmentTag("prevents_ice_melting"); + public static final EnchantmentTag PREVENTS_INFESTED_SPAWNS = new EnchantmentTag("prevents_infested_spawns"); + public static final EnchantmentTag TREASURE = new EnchantmentTag("treasure"); + public static final EnchantmentTag NON_TREASURE = new EnchantmentTag("non_treasure"); + public static final EnchantmentTag TRADES_DESERT_COMMON = new EnchantmentTag("trades/desert_common"); + public static final EnchantmentTag TRADES_JUNGLE_COMMON = new EnchantmentTag("trades/jungle_common"); + public static final EnchantmentTag TRADES_PLAINS_COMMON = new EnchantmentTag("trades/plains_common"); + public static final EnchantmentTag TRADES_SAVANNA_COMMON = new EnchantmentTag("trades/savanna_common"); + public static final EnchantmentTag TRADES_SNOW_COMMON = new EnchantmentTag("trades/snow_common"); + public static final EnchantmentTag TRADES_SWAMP_COMMON = new EnchantmentTag("trades/swamp_common"); + public static final EnchantmentTag TRADES_TAIGA_COMMON = new EnchantmentTag("trades/taiga_common"); + public static final EnchantmentTag TRADES_DESERT_SPECIAL = new EnchantmentTag("trades/desert_special"); + public static final EnchantmentTag TRADES_JUNGLE_SPECIAL = new EnchantmentTag("trades/jungle_special"); + public static final EnchantmentTag TRADES_PLAINS_SPECIAL = new EnchantmentTag("trades/plains_special"); + public static final EnchantmentTag TRADES_SAVANNA_SPECIAL = new EnchantmentTag("trades/savanna_special"); + public static final EnchantmentTag TRADES_SNOW_SPECIAL = new EnchantmentTag("trades/snow_special"); + public static final EnchantmentTag TRADES_SWAMP_SPECIAL = new EnchantmentTag("trades/swamp_special"); + public static final EnchantmentTag TRADES_TAIGA_SPECIAL = new EnchantmentTag("trades/taiga_special"); + + private final int id; + + private EnchantmentTag(String identifier) { + this.id = ALL_ENCHANTMENT_TAGS.size(); + register(identifier, this); + } + + @Override + public int ordinal() { + return id; + } + + private static void register(String name, EnchantmentTag tag) { + ALL_ENCHANTMENT_TAGS.put(("minecraft:" + name).intern(), 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 index f064d0763..e1fbf4634 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 @@ -25,44 +25,176 @@ package org.geysermc.geyser.session.cache.tags; -import org.geysermc.geyser.session.cache.TagCache; +import org.geysermc.geyser.util.Ordered; -public enum ItemTag { - AXOLOTL_FOOD("axolotl_food"), - CREEPER_IGNITERS("creeper_igniters"), - FISHES("fishes"), - FOX_FOOD("fox_food"), - PIGLIN_LOVED("piglin_loved"), - SMALL_FLOWERS("small_flowers"), - 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"); +import java.util.HashMap; +import java.util.Map; + +@SuppressWarnings("unused") +public final class ItemTag implements Ordered { + public static final Map ALL_ITEM_TAGS = new HashMap<>(); + + public static final ItemTag WOOL = new ItemTag("wool"); + public static final ItemTag PLANKS = new ItemTag("planks"); + public static final ItemTag STONE_BRICKS = new ItemTag("stone_bricks"); + public static final ItemTag WOODEN_BUTTONS = new ItemTag("wooden_buttons"); + public static final ItemTag STONE_BUTTONS = new ItemTag("stone_buttons"); + public static final ItemTag BUTTONS = new ItemTag("buttons"); + public static final ItemTag WOOL_CARPETS = new ItemTag("wool_carpets"); + public static final ItemTag WOODEN_DOORS = new ItemTag("wooden_doors"); + public static final ItemTag WOODEN_STAIRS = new ItemTag("wooden_stairs"); + public static final ItemTag WOODEN_SLABS = new ItemTag("wooden_slabs"); + public static final ItemTag WOODEN_FENCES = new ItemTag("wooden_fences"); + public static final ItemTag FENCE_GATES = new ItemTag("fence_gates"); + public static final ItemTag WOODEN_PRESSURE_PLATES = new ItemTag("wooden_pressure_plates"); + public static final ItemTag WOODEN_TRAPDOORS = new ItemTag("wooden_trapdoors"); + public static final ItemTag DOORS = new ItemTag("doors"); + public static final ItemTag SAPLINGS = new ItemTag("saplings"); + public static final ItemTag LOGS_THAT_BURN = new ItemTag("logs_that_burn"); + public static final ItemTag LOGS = new ItemTag("logs"); + public static final ItemTag DARK_OAK_LOGS = new ItemTag("dark_oak_logs"); + public static final ItemTag OAK_LOGS = new ItemTag("oak_logs"); + public static final ItemTag BIRCH_LOGS = new ItemTag("birch_logs"); + public static final ItemTag ACACIA_LOGS = new ItemTag("acacia_logs"); + public static final ItemTag CHERRY_LOGS = new ItemTag("cherry_logs"); + public static final ItemTag JUNGLE_LOGS = new ItemTag("jungle_logs"); + public static final ItemTag SPRUCE_LOGS = new ItemTag("spruce_logs"); + public static final ItemTag MANGROVE_LOGS = new ItemTag("mangrove_logs"); + public static final ItemTag CRIMSON_STEMS = new ItemTag("crimson_stems"); + public static final ItemTag WARPED_STEMS = new ItemTag("warped_stems"); + public static final ItemTag BAMBOO_BLOCKS = new ItemTag("bamboo_blocks"); + public static final ItemTag WART_BLOCKS = new ItemTag("wart_blocks"); + public static final ItemTag BANNERS = new ItemTag("banners"); + public static final ItemTag SAND = new ItemTag("sand"); + public static final ItemTag SMELTS_TO_GLASS = new ItemTag("smelts_to_glass"); + public static final ItemTag STAIRS = new ItemTag("stairs"); + public static final ItemTag SLABS = new ItemTag("slabs"); + public static final ItemTag WALLS = new ItemTag("walls"); + public static final ItemTag ANVIL = new ItemTag("anvil"); + public static final ItemTag RAILS = new ItemTag("rails"); + public static final ItemTag LEAVES = new ItemTag("leaves"); + public static final ItemTag TRAPDOORS = new ItemTag("trapdoors"); + public static final ItemTag SMALL_FLOWERS = new ItemTag("small_flowers"); + public static final ItemTag BEDS = new ItemTag("beds"); + public static final ItemTag FENCES = new ItemTag("fences"); + public static final ItemTag TALL_FLOWERS = new ItemTag("tall_flowers"); + public static final ItemTag FLOWERS = new ItemTag("flowers"); + public static final ItemTag PIGLIN_REPELLENTS = new ItemTag("piglin_repellents"); + public static final ItemTag PIGLIN_LOVED = new ItemTag("piglin_loved"); + public static final ItemTag IGNORED_BY_PIGLIN_BABIES = new ItemTag("ignored_by_piglin_babies"); + public static final ItemTag MEAT = new ItemTag("meat"); + public static final ItemTag SNIFFER_FOOD = new ItemTag("sniffer_food"); + public static final ItemTag PIGLIN_FOOD = new ItemTag("piglin_food"); + public static final ItemTag FOX_FOOD = new ItemTag("fox_food"); + public static final ItemTag COW_FOOD = new ItemTag("cow_food"); + public static final ItemTag GOAT_FOOD = new ItemTag("goat_food"); + public static final ItemTag SHEEP_FOOD = new ItemTag("sheep_food"); + public static final ItemTag WOLF_FOOD = new ItemTag("wolf_food"); + public static final ItemTag CAT_FOOD = new ItemTag("cat_food"); + public static final ItemTag HORSE_FOOD = new ItemTag("horse_food"); + public static final ItemTag HORSE_TEMPT_ITEMS = new ItemTag("horse_tempt_items"); + public static final ItemTag CAMEL_FOOD = new ItemTag("camel_food"); + public static final ItemTag ARMADILLO_FOOD = new ItemTag("armadillo_food"); + public static final ItemTag BEE_FOOD = new ItemTag("bee_food"); + public static final ItemTag CHICKEN_FOOD = new ItemTag("chicken_food"); + public static final ItemTag FROG_FOOD = new ItemTag("frog_food"); + public static final ItemTag HOGLIN_FOOD = new ItemTag("hoglin_food"); + public static final ItemTag LLAMA_FOOD = new ItemTag("llama_food"); + public static final ItemTag LLAMA_TEMPT_ITEMS = new ItemTag("llama_tempt_items"); + public static final ItemTag OCELOT_FOOD = new ItemTag("ocelot_food"); + public static final ItemTag PANDA_FOOD = new ItemTag("panda_food"); + public static final ItemTag PIG_FOOD = new ItemTag("pig_food"); + public static final ItemTag RABBIT_FOOD = new ItemTag("rabbit_food"); + public static final ItemTag STRIDER_FOOD = new ItemTag("strider_food"); + public static final ItemTag STRIDER_TEMPT_ITEMS = new ItemTag("strider_tempt_items"); + public static final ItemTag TURTLE_FOOD = new ItemTag("turtle_food"); + public static final ItemTag PARROT_FOOD = new ItemTag("parrot_food"); + public static final ItemTag PARROT_POISONOUS_FOOD = new ItemTag("parrot_poisonous_food"); + public static final ItemTag AXOLOTL_FOOD = new ItemTag("axolotl_food"); + public static final ItemTag GOLD_ORES = new ItemTag("gold_ores"); + public static final ItemTag IRON_ORES = new ItemTag("iron_ores"); + public static final ItemTag DIAMOND_ORES = new ItemTag("diamond_ores"); + public static final ItemTag REDSTONE_ORES = new ItemTag("redstone_ores"); + public static final ItemTag LAPIS_ORES = new ItemTag("lapis_ores"); + public static final ItemTag COAL_ORES = new ItemTag("coal_ores"); + public static final ItemTag EMERALD_ORES = new ItemTag("emerald_ores"); + public static final ItemTag COPPER_ORES = new ItemTag("copper_ores"); + public static final ItemTag NON_FLAMMABLE_WOOD = new ItemTag("non_flammable_wood"); + public static final ItemTag SOUL_FIRE_BASE_BLOCKS = new ItemTag("soul_fire_base_blocks"); + public static final ItemTag CANDLES = new ItemTag("candles"); + public static final ItemTag DIRT = new ItemTag("dirt"); + public static final ItemTag TERRACOTTA = new ItemTag("terracotta"); + public static final ItemTag COMPLETES_FIND_TREE_TUTORIAL = new ItemTag("completes_find_tree_tutorial"); + public static final ItemTag BOATS = new ItemTag("boats"); + public static final ItemTag CHEST_BOATS = new ItemTag("chest_boats"); + public static final ItemTag FISHES = new ItemTag("fishes"); + public static final ItemTag SIGNS = new ItemTag("signs"); + public static final ItemTag CREEPER_DROP_MUSIC_DISCS = new ItemTag("creeper_drop_music_discs"); + public static final ItemTag COALS = new ItemTag("coals"); + public static final ItemTag ARROWS = new ItemTag("arrows"); + public static final ItemTag LECTERN_BOOKS = new ItemTag("lectern_books"); + public static final ItemTag BOOKSHELF_BOOKS = new ItemTag("bookshelf_books"); + public static final ItemTag BEACON_PAYMENT_ITEMS = new ItemTag("beacon_payment_items"); + public static final ItemTag STONE_TOOL_MATERIALS = new ItemTag("stone_tool_materials"); + public static final ItemTag STONE_CRAFTING_MATERIALS = new ItemTag("stone_crafting_materials"); + public static final ItemTag FREEZE_IMMUNE_WEARABLES = new ItemTag("freeze_immune_wearables"); + public static final ItemTag DAMPENS_VIBRATIONS = new ItemTag("dampens_vibrations"); + public static final ItemTag CLUSTER_MAX_HARVESTABLES = new ItemTag("cluster_max_harvestables"); + public static final ItemTag COMPASSES = new ItemTag("compasses"); + public static final ItemTag HANGING_SIGNS = new ItemTag("hanging_signs"); + public static final ItemTag CREEPER_IGNITERS = new ItemTag("creeper_igniters"); + public static final ItemTag NOTEBLOCK_TOP_INSTRUMENTS = new ItemTag("noteblock_top_instruments"); + public static final ItemTag FOOT_ARMOR = new ItemTag("foot_armor"); + public static final ItemTag LEG_ARMOR = new ItemTag("leg_armor"); + public static final ItemTag CHEST_ARMOR = new ItemTag("chest_armor"); + public static final ItemTag HEAD_ARMOR = new ItemTag("head_armor"); + public static final ItemTag SKULLS = new ItemTag("skulls"); + public static final ItemTag TRIMMABLE_ARMOR = new ItemTag("trimmable_armor"); + public static final ItemTag TRIM_MATERIALS = new ItemTag("trim_materials"); + public static final ItemTag TRIM_TEMPLATES = new ItemTag("trim_templates"); + public static final ItemTag DECORATED_POT_SHERDS = new ItemTag("decorated_pot_sherds"); + public static final ItemTag DECORATED_POT_INGREDIENTS = new ItemTag("decorated_pot_ingredients"); + public static final ItemTag SWORDS = new ItemTag("swords"); + public static final ItemTag AXES = new ItemTag("axes"); + public static final ItemTag HOES = new ItemTag("hoes"); + public static final ItemTag PICKAXES = new ItemTag("pickaxes"); + public static final ItemTag SHOVELS = new ItemTag("shovels"); + public static final ItemTag BREAKS_DECORATED_POTS = new ItemTag("breaks_decorated_pots"); + public static final ItemTag VILLAGER_PLANTABLE_SEEDS = new ItemTag("villager_plantable_seeds"); + public static final ItemTag DYEABLE = new ItemTag("dyeable"); + public static final ItemTag ENCHANTABLE_FOOT_ARMOR = new ItemTag("enchantable/foot_armor"); + public static final ItemTag ENCHANTABLE_LEG_ARMOR = new ItemTag("enchantable/leg_armor"); + public static final ItemTag ENCHANTABLE_CHEST_ARMOR = new ItemTag("enchantable/chest_armor"); + public static final ItemTag ENCHANTABLE_HEAD_ARMOR = new ItemTag("enchantable/head_armor"); + public static final ItemTag ENCHANTABLE_ARMOR = new ItemTag("enchantable/armor"); + public static final ItemTag ENCHANTABLE_SWORD = new ItemTag("enchantable/sword"); + public static final ItemTag ENCHANTABLE_FIRE_ASPECT = new ItemTag("enchantable/fire_aspect"); + public static final ItemTag ENCHANTABLE_SHARP_WEAPON = new ItemTag("enchantable/sharp_weapon"); + public static final ItemTag ENCHANTABLE_WEAPON = new ItemTag("enchantable/weapon"); + public static final ItemTag ENCHANTABLE_MINING = new ItemTag("enchantable/mining"); + public static final ItemTag ENCHANTABLE_MINING_LOOT = new ItemTag("enchantable/mining_loot"); + public static final ItemTag ENCHANTABLE_FISHING = new ItemTag("enchantable/fishing"); + public static final ItemTag ENCHANTABLE_TRIDENT = new ItemTag("enchantable/trident"); + public static final ItemTag ENCHANTABLE_DURABILITY = new ItemTag("enchantable/durability"); + public static final ItemTag ENCHANTABLE_BOW = new ItemTag("enchantable/bow"); + public static final ItemTag ENCHANTABLE_EQUIPPABLE = new ItemTag("enchantable/equippable"); + public static final ItemTag ENCHANTABLE_CROSSBOW = new ItemTag("enchantable/crossbow"); + public static final ItemTag ENCHANTABLE_VANISHING = new ItemTag("enchantable/vanishing"); + public static final ItemTag ENCHANTABLE_MACE = new ItemTag("enchantable/mace"); + + private final int id; - ItemTag(String identifier) { + private ItemTag(String identifier) { + this.id = ALL_ITEM_TAGS.size(); register(identifier, this); } + @Override + public int ordinal() { + return id; + } + private static void register(String name, ItemTag tag) { - TagCache.ALL_ITEM_TAGS.put("minecraft:" + name, tag); + ALL_ITEM_TAGS.put(("minecraft:" + name).intern(), tag); } } 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 e1407346a..b51d86d13 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 @@ -36,15 +36,14 @@ 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.PlayerEnchantOptionsPacket; import org.geysermc.geyser.inventory.*; -import org.geysermc.geyser.inventory.item.Enchantment; import org.geysermc.geyser.inventory.updater.UIInventoryUpdater; +import org.geysermc.geyser.item.enchantment.Enchantment; import org.geysermc.geyser.level.block.Blocks; 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; public class EnchantingInventoryTranslator extends AbstractBlockInventoryTranslator { public EnchantingInventoryTranslator() { @@ -73,16 +72,16 @@ public class EnchantingInventoryTranslator extends AbstractBlockInventoryTransla // The Bedrock index might need changed, so let's look it up and see. int bedrockIndex = value; if (bedrockIndex != -1) { - Enchantment enchantment = Enchantment.getByJavaIdentifier("minecraft:" + Enchantment.JavaEnchantment.of(bedrockIndex).name().toLowerCase(Locale.ROOT)); - if (enchantment != null) { + Enchantment enchantment = session.getRegistryCache().enchantments().byId(value); + if (enchantment != null && enchantment.bedrockEnchantment() != null) { // Convert the Java enchantment index to Bedrock's - bedrockIndex = enchantment.ordinal(); + bedrockIndex = enchantment.bedrockEnchantment().ordinal(); } else { // There is no Bedrock enchantment equivalent bedrockIndex = -1; } } - enchantingInventory.getGeyserEnchantOptions()[slotToUpdate].setEnchantIndex(value, bedrockIndex); + enchantingInventory.getGeyserEnchantOptions()[slotToUpdate].setEnchantIndex(bedrockIndex); break; case 7: case 8: 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 89c50b12f..1ecc5bf82 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 @@ -26,11 +26,6 @@ package org.geysermc.geyser.translator.protocol.java; import com.google.common.base.Suppliers; -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; @@ -46,13 +41,18 @@ import org.cloudburstmc.protocol.bedrock.packet.AvailableCommandsPacket; 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.item.enchantment.Enchantment; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; 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.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 java.util.*; import java.util.function.Supplier; @@ -267,7 +267,7 @@ public class JavaCommandsTranslator extends PacketTranslator ATTRIBUTES; - case "minecraft:enchantment" -> Enchantment.JavaEnchantment.ALL_JAVA_IDENTIFIERS; + case "minecraft:enchantment" -> context.getEnchantments(); case "minecraft:entity_type" -> context.getEntityTypes(); case "minecraft:mob_effect" -> ALL_EFFECT_IDENTIFIERS; case "minecraft:worldgen/biome" -> tags ? context.getBiomesWithTags() : context.getBiomes(); @@ -292,6 +292,7 @@ public class JavaCommandsTranslator extends PacketTranslator session.getTagCache().is(BlockTag.AXE_EFFECTIVE, block); - case "hoe" -> session.getTagCache().is(BlockTag.HOE_EFFECTIVE, block); - case "pickaxe" -> session.getTagCache().is(BlockTag.PICKAXE_EFFECTIVE, block); + case "axe" -> session.getTagCache().is(BlockTag.MINEABLE_AXE, block); + case "hoe" -> session.getTagCache().is(BlockTag.MINEABLE_HOE, block); + case "pickaxe" -> session.getTagCache().is(BlockTag.MINEABLE_PICKAXE, block); case "shears" -> session.getTagCache().is(BlockTag.LEAVES, block) || session.getTagCache().is(BlockTag.WOOL, block); - case "shovel" -> session.getTagCache().is(BlockTag.SHOVEL_EFFECTIVE, block); + case "shovel" -> session.getTagCache().is(BlockTag.MINEABLE_SHOVEL, block); case "sword" -> block == Blocks.COBWEB; default -> { session.getGeyser().getLogger().warning("Unknown tool type: " + itemToolType); @@ -145,7 +145,7 @@ public final class BlockUtils { toolCanBreak = canToolTierBreakBlock(session, block, toolTier); } - int toolEfficiencyLevel = ItemUtils.getEnchantmentLevel(components, Enchantment.JavaEnchantment.EFFICIENCY); + int toolEfficiencyLevel = ItemUtils.getEnchantmentLevel(session, components, BedrockEnchantment.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) < 1; + ItemUtils.getEnchantmentLevel(session, session.getPlayerInventory().getItem(5).getComponents(), BedrockEnchantment.AQUA_AFFINITY) < 1; return calculateBreakTime(block.destroyTime(), 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 c9d9903d4..bbb64a41e 100644 --- a/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java @@ -27,17 +27,26 @@ 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.inventory.item.BedrockEnchantment; import org.geysermc.geyser.item.Items; +import org.geysermc.geyser.item.enchantment.Enchantment; +import org.geysermc.geyser.item.enchantment.EnchantmentComponent; import org.geysermc.geyser.item.type.FishingRodItem; import org.geysermc.geyser.item.type.Item; +import org.geysermc.geyser.session.GeyserSession; 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 { +import java.util.Map; - public static int getEnchantmentLevel(@Nullable DataComponents components, Enchantment.JavaEnchantment enchantment) { +public final class ItemUtils { + + /** + * Cheap hack. Proper solution is to read the enchantment effects. + */ + @Deprecated + public static int getEnchantmentLevel(GeyserSession session, @Nullable DataComponents components, BedrockEnchantment bedrockEnchantment) { if (components == null) { return 0; } @@ -47,7 +56,32 @@ public class ItemUtils { return 0; } - return enchantmentData.getEnchantments().getOrDefault(enchantment.ordinal(), 0); + for (Map.Entry entry : enchantmentData.getEnchantments().entrySet()) { + Enchantment enchantment = session.getRegistryCache().enchantments().byId(entry.getKey()); + if (enchantment.bedrockEnchantment() == bedrockEnchantment) { + return entry.getValue(); + } + } + return 0; + } + + public static boolean hasEffect(GeyserSession session, @Nullable DataComponents components, EnchantmentComponent component) { + if (components == null) { + return false; + } + + ItemEnchantments enchantmentData = components.get(DataComponentType.ENCHANTMENTS); + if (enchantmentData == null) { + return false; + } + + for (Integer id : enchantmentData.getEnchantments().keySet()) { + Enchantment enchantment = session.getRegistryCache().enchantments().byId(id); + if (enchantment.effects().contains(component)) { + return true; + } + } + return false; } /** @@ -73,4 +107,7 @@ public class ItemUtils { } return components.get(DataComponentType.CUSTOM_NAME); } + + private ItemUtils() { + } } diff --git a/core/src/main/java/org/geysermc/geyser/item/Enchantment.java b/core/src/main/java/org/geysermc/geyser/util/Ordered.java similarity index 55% rename from core/src/main/java/org/geysermc/geyser/item/Enchantment.java rename to core/src/main/java/org/geysermc/geyser/util/Ordered.java index 506467afd..08ff5df72 100644 --- a/core/src/main/java/org/geysermc/geyser/item/Enchantment.java +++ b/core/src/main/java/org/geysermc/geyser/util/Ordered.java @@ -23,25 +23,11 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.geyser.item; - -import org.checkerframework.checker.nullness.qual.Nullable; -import org.cloudburstmc.nbt.NbtMap; -import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; +package org.geysermc.geyser.util; /** - * @param anvilCost also as a rarity multiplier + * Represents anything that could be tracked like a enum, without also creating a name and enum-wide array. */ -public record Enchantment(String supportedItemsTag, int maxLevel, int anvilCost, @Nullable String exclusiveSetTag) { - - // Implementation note: I have a feeling the tags can be a list of items, because in vanilla they're HolderSet classes. - // I'm not sure how that's wired over the network, so we'll put it off. - public static Enchantment read(RegistryEntry entry) { - NbtMap data = entry.getData(); - String supportedItems = data.getString("supported_items"); - int maxLevel = data.getInt("max_level"); - int anvilCost = data.getInt("anvil_cost"); - String exclusiveSet = data.getString("exclusive_set", null); - return new Enchantment(supportedItems, maxLevel, anvilCost, exclusiveSet); - } +public interface Ordered { + int ordinal(); } diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings index 88e50df10..1f1d5ce8c 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 88e50df1008916c266428ac11f76f07dc24638c5 +Subproject commit 1f1d5ce8c482dac142f13e95e19368e3f36de144 From 3ead9e94aa3aefd35db170027f1c8eff240f30b6 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Mon, 3 Jun 2024 23:48:45 -0400 Subject: [PATCH 053/233] More unneeded classes --- .../inventory/item/BedrockEnchantment.java | 48 ------------------- .../geyser/registry/type/EnchantmentData.java | 35 -------------- 2 files changed, 83 deletions(-) delete mode 100644 core/src/main/java/org/geysermc/geyser/registry/type/EnchantmentData.java diff --git a/core/src/main/java/org/geysermc/geyser/inventory/item/BedrockEnchantment.java b/core/src/main/java/org/geysermc/geyser/inventory/item/BedrockEnchantment.java index a9125421e..6d3fdbc27 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/BedrockEnchantment.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/item/BedrockEnchantment.java @@ -95,52 +95,4 @@ public enum BedrockEnchantment { } return null; } - - /** - * Enchantments classified by their Java index - */ - public enum JavaEnchantment { - PROTECTION, - FIRE_PROTECTION, - FEATHER_FALLING, - BLAST_PROTECTION, - PROJECTILE_PROTECTION, - RESPIRATION, - AQUA_AFFINITY, - THORNS, - DEPTH_STRIDER, - FROST_WALKER, - BINDING_CURSE, - SOUL_SPEED, - SWIFT_SNEAK, - SHARPNESS, - SMITE, - BANE_OF_ARTHROPODS, - KNOCKBACK, - FIRE_ASPECT, - LOOTING, - SWEEPING_EDGE, - EFFICIENCY, - SILK_TOUCH, - UNBREAKING, - FORTUNE, - POWER, - PUNCH, - FLAME, - INFINITY, - LUCK_OF_THE_SEA, - LURE, - LOYALTY, - IMPALING, - RIPTIDE, - CHANNELING, - MULTISHOT, - QUICK_CHARGE, - PIERCING, - DENSITY, - BREACH, - WIND_BURST, - MENDING, - VANISHING_CURSE; - } } diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/EnchantmentData.java b/core/src/main/java/org/geysermc/geyser/registry/type/EnchantmentData.java deleted file mode 100644 index d341cd9e3..000000000 --- a/core/src/main/java/org/geysermc/geyser/registry/type/EnchantmentData.java +++ /dev/null @@ -1,35 +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.registry.type; - -import it.unimi.dsi.fastutil.ints.IntSet; -import org.geysermc.geyser.inventory.item.BedrockEnchantment.JavaEnchantment; - -import java.util.Set; - -public record EnchantmentData(int rarityMultiplier, int maxLevel, Set incompatibleEnchantments, - IntSet validItems) { -} From 087322f6cd9b2e61979c5561ab59a795e4ecd3a6 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 4 Jun 2024 00:01:59 -0400 Subject: [PATCH 054/233] Small set optimization --- .../org/geysermc/geyser/item/enchantment/Enchantment.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java b/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java index 41cc36894..8d1d92f6c 100644 --- a/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java +++ b/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java @@ -66,16 +66,13 @@ public record Enchantment(String identifier, } private static Set readEnchantmentComponents(NbtMap effects) { - if (effects.isEmpty()) { - return Collections.emptySet(); - } Set components = new HashSet<>(); for (Map.Entry entry : effects.entrySet()) { switch (entry.getKey()) { case "minecraft:prevent_armor_change" -> components.add(EnchantmentComponent.PREVENT_ARMOR_CHANGE); } } - return components; + return Set.copyOf(components); // Also ensures any empty sets are consolidated } private static String readDescription(NbtMap tag) { From 688b642520fa8c14c09667003f0d61dd1c552044 Mon Sep 17 00:00:00 2001 From: chris Date: Tue, 4 Jun 2024 22:14:42 +0200 Subject: [PATCH 055/233] Ignore PurchaseReceiptPacket (#4719) --- .../main/java/org/geysermc/geyser/network/CodecProcessor.java | 4 ++-- 1 file changed, 2 insertions(+), 2 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 6bd767fb7..b91f8d7dc 100644 --- a/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java +++ b/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java @@ -232,8 +232,8 @@ class CodecProcessor { .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) + // Unused serverbound packets for featured servers, which is for some reason still occasionally sent + .updateSerializer(PurchaseReceiptPacket.class, IGNORED_SERIALIZER) // Illegal unused serverbound packets that are deprecated .updateSerializer(ClientCheatAbilityPacket.class, ILLEGAL_SERIALIZER) // Illegal unusued serverbound packets that relate to unused features From 42ae9eba559f947e1b4fdd15c2ff0f47f4cc26bb Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 4 Jun 2024 17:09:57 -0400 Subject: [PATCH 056/233] Fix air bubbles for Bedrock 1.21 --- .../entity/type/player/SessionPlayerEntity.java | 12 +++++++++++- .../geyser/network/UpstreamPacketHandler.java | 2 ++ 2 files changed, 13 insertions(+), 1 deletion(-) 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 44b28ceaa..ad6729c42 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 @@ -31,9 +31,11 @@ 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; +import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; import org.geysermc.geyser.entity.attribute.GeyserAttributeType; import org.geysermc.geyser.item.Items; +import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.AttributeUtils; import org.geysermc.geyser.util.DimensionUtils; @@ -65,6 +67,8 @@ public class SessionPlayerEntity extends PlayerEntity { @Getter private boolean isRidingInFront; + private int lastAirSupply = getMaxAir(); + public SessionPlayerEntity(GeyserSession session) { super(session, -1, 1, null, Vector3f.ZERO, Vector3f.ZERO, 0, 0, 0, null, null); @@ -159,7 +163,13 @@ public class SessionPlayerEntity extends PlayerEntity { @Override protected void setAirSupply(int amount) { - if (amount == getMaxAir()) { + // Seemingly required to be sent as of Bedrock 1.21. Otherwise, bubbles will appear as empty + // Also, this changes how the air bubble graphics/sounds are presented. Breathing on means sound effects and + // the bubbles visually pop + setFlag(EntityFlag.BREATHING, amount >= this.lastAirSupply); + this.lastAirSupply = amount; + + if (amount == getMaxAir() && GameProtocol.isPre1_21_0(session)) { super.setAirSupply(0); // Hide the bubble counter from the UI for the player } else { super.setAirSupply(amount); 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 23ab1697f..c7aabb806 100644 --- a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java @@ -132,6 +132,8 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { } session.getUpstream().getSession().setCodec(packetCodec); + // FIXME temporary until 1.20.80 is dropped + session.getPlayerEntity().resetAir(); return true; } From fcdd1b91a1bcf3b9277927d13c09bf0959e3ad23 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 4 Jun 2024 22:47:31 -0400 Subject: [PATCH 057/233] New banner patterns --- .../org/geysermc/geyser/inventory/item/BannerPattern.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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..b6cc2c206 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 @@ -72,7 +72,9 @@ public enum BannerPattern { SKULL("sku"), FLOWER("flo"), MOJANG("moj"), - PIGLIN("pig"); + PIGLIN("pig"), + FLOW("flw"), + GUSTER("gus"); private static final BannerPattern[] VALUES = values(); From 4ee9dd5d1708858c7842068b55187d7cba36fe4e Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Wed, 5 Jun 2024 16:45:11 -0400 Subject: [PATCH 058/233] New potions and merge potion enums --- .../geyser/entity/type/ArrowEntity.java | 9 +- .../geyser/inventory/item/Potion.java | 137 +++++++++++----- .../inventory/item/TippedArrowPotion.java | 153 ------------------ .../geysermc/geyser/item/type/ArrowItem.java | 10 +- .../geyser/item/type/TippedArrowItem.java | 8 +- 5 files changed, 104 insertions(+), 213 deletions(-) delete mode 100644 core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ArrowEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ArrowEntity.java index 1ee706811..ba1241434 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/ArrowEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/ArrowEntity.java @@ -28,7 +28,7 @@ package org.geysermc.geyser.entity.type; 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.inventory.item.Potion; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; @@ -46,12 +46,7 @@ public class ArrowEntity extends AbstractArrowEntity { if (potionColor == -1) { dirtyMetadata.put(EntityDataTypes.CUSTOM_DISPLAY, (byte) 0); } else { - TippedArrowPotion potion = TippedArrowPotion.getByJavaColor(potionColor); - if (potion != null && potion.getJavaColor() != -1) { - dirtyMetadata.put(EntityDataTypes.CUSTOM_DISPLAY, (byte) potion.getBedrockId()); - } else { - dirtyMetadata.put(EntityDataTypes.CUSTOM_DISPLAY, (byte) 0); - } + dirtyMetadata.put(EntityDataTypes.CUSTOM_DISPLAY, Potion.toTippedArrowId(potionColor)); } } } 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 86c19de80..c4d20c623 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 @@ -34,57 +34,68 @@ import java.util.Locale; @Getter public enum Potion { - WATER(0), - MUNDANE(1), - THICK(3), - AWKWARD(4), - NIGHT_VISION(5), - LONG_NIGHT_VISION(6), - INVISIBILITY(7), - LONG_INVISIBILITY(8), - LEAPING(9), - LONG_LEAPING(10), - STRONG_LEAPING(11), - FIRE_RESISTANCE(12), - LONG_FIRE_RESISTANCE(13), - SWIFTNESS(14), - LONG_SWIFTNESS(15), - STRONG_SWIFTNESS(16), - SLOWNESS(17), - 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), - STRONG_HEALING(22), - HARMING(23), - STRONG_HARMING(24), - POISON(25), - LONG_POISON(26), - STRONG_POISON(27), - REGENERATION(28), - LONG_REGENERATION(29), - STRONG_REGENERATION(30), - STRENGTH(31), - LONG_STRENGTH(32), - STRONG_STRENGTH(33), - WEAKNESS(34), - LONG_WEAKNESS(35), - LUCK(2), //does not exist - SLOW_FALLING(40), - LONG_SLOW_FALLING(41); + WATER(0, ArrowParticleColors.NONE), + MUNDANE(1, ArrowParticleColors.NONE), // 2 is extended? + THICK(3, ArrowParticleColors.NONE), + AWKWARD(4, ArrowParticleColors.NONE), + NIGHT_VISION(5, ArrowParticleColors.NIGHT_VISION), + LONG_NIGHT_VISION(6, ArrowParticleColors.NIGHT_VISION), + INVISIBILITY(7, ArrowParticleColors.INVISIBILITY), + LONG_INVISIBILITY(8, ArrowParticleColors.INVISIBILITY), + LEAPING(9, ArrowParticleColors.LEAPING), + LONG_LEAPING(10, ArrowParticleColors.LEAPING), + STRONG_LEAPING(11, ArrowParticleColors.LEAPING), + FIRE_RESISTANCE(12, ArrowParticleColors.FIRE_RESISTANCE), + LONG_FIRE_RESISTANCE(13, ArrowParticleColors.FIRE_RESISTANCE), + SWIFTNESS(14, ArrowParticleColors.SWIFTNESS), + LONG_SWIFTNESS(15, ArrowParticleColors.SWIFTNESS), + STRONG_SWIFTNESS(16, ArrowParticleColors.SWIFTNESS), + SLOWNESS(17, ArrowParticleColors.SLOWNESS), + LONG_SLOWNESS(18, ArrowParticleColors.SLOWNESS), + STRONG_SLOWNESS(42, ArrowParticleColors.SLOWNESS), + TURTLE_MASTER(37, ArrowParticleColors.TURTLE_MASTER), + LONG_TURTLE_MASTER(38, ArrowParticleColors.TURTLE_MASTER), + STRONG_TURTLE_MASTER(39, ArrowParticleColors.TURTLE_MASTER), + WATER_BREATHING(19, ArrowParticleColors.WATER_BREATHING), + LONG_WATER_BREATHING(20, ArrowParticleColors.WATER_BREATHING), + HEALING(21, ArrowParticleColors.HEALING), + STRONG_HEALING(22, ArrowParticleColors.HEALING), + HARMING(23, ArrowParticleColors.HARMING), + STRONG_HARMING(24, ArrowParticleColors.HARMING), + POISON(25, ArrowParticleColors.POISON), + LONG_POISON(26, ArrowParticleColors.POISON), + STRONG_POISON(27, ArrowParticleColors.POISON), + REGENERATION(28, ArrowParticleColors.REGENERATION), + LONG_REGENERATION(29, ArrowParticleColors.REGENERATION), + STRONG_REGENERATION(30, ArrowParticleColors.REGENERATION), + STRENGTH(31, ArrowParticleColors.STRENGTH), + LONG_STRENGTH(32, ArrowParticleColors.STRENGTH), + STRONG_STRENGTH(33, ArrowParticleColors.STRENGTH), + WEAKNESS(34, ArrowParticleColors.WEAKNESS), + LONG_WEAKNESS(35, ArrowParticleColors.WEAKNESS), + LUCK(2, ArrowParticleColors.NONE), // does not exist in Bedrock + SLOW_FALLING(40, ArrowParticleColors.SLOW_FALLING), + LONG_SLOW_FALLING(41, ArrowParticleColors.SLOW_FALLING), + WIND_CHARGING(43, ArrowParticleColors.WIND_CHARGING), + WEAVING(44, ArrowParticleColors.WEAVING), + OOZING(45, ArrowParticleColors.OOZING), + INFESTATION(46, ArrowParticleColors.INFESTATION); public static final Potion[] VALUES = values(); private final String javaIdentifier; private final short bedrockId; + private final int javaColor; - Potion(int bedrockId) { + Potion(int bedrockId, int javaColor) { this.javaIdentifier = "minecraft:" + this.name().toLowerCase(Locale.ENGLISH); this.bedrockId = (short) bedrockId; + this.javaColor = javaColor; + } + + public int tippedArrowId() { + // +1 likely to offset 0 as nothing? + return this.bedrockId + 1; } public PotionContents toComponent() { @@ -106,4 +117,44 @@ public enum Potion { } return null; } + + public static @Nullable Potion getByTippedArrowDamage(int bedrockId) { + return getByBedrockId(bedrockId - 1); + } + + public static byte toTippedArrowId(int javaParticleColor) { + for (Potion potion : VALUES) { + if (potion.javaColor == javaParticleColor) { + return (byte) (potion.bedrockId + 1); + } + } + return (byte) 0; + } + + /** + * For tipped arrow usage + */ + private static final class ArrowParticleColors { + static final int NONE = 1; + static final int NIGHT_VISION = 2039713; + static final int INVISIBILITY = 8356754; + static final int LEAPING = 2293580; + static final int FIRE_RESISTANCE = 14981690; + static final int SWIFTNESS = 8171462; + static final int SLOWNESS = 5926017; + static final int TURTLE_MASTER = 7691106; + static final int WATER_BREATHING = 3035801; + static final int HEALING = 16262179; + static final int HARMING = 4393481; + static final int POISON = 5149489; + static final int REGENERATION = 13458603; + static final int STRENGTH = 9643043; + static final int WEAKNESS = 4738376; + static final int LUCK = 3381504; + static final int SLOW_FALLING = 16773073; + static final int WIND_CHARGING = 12438015; + static final int WEAVING = 7891290; + static final int OOZING = 10092451; + static final int INFESTATION = 9214860; + } } 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 deleted file mode 100644 index b849e07e2..000000000 --- a/core/src/main/java/org/geysermc/geyser/inventory/item/TippedArrowPotion.java +++ /dev/null @@ -1,153 +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.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. - * See here - */ -@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), - NIGHT_VISION(6, ArrowParticleColors.NIGHT_VISION), - LONG_NIGHT_VISION(7, ArrowParticleColors.NIGHT_VISION), - INVISIBILITY(8, ArrowParticleColors.INVISIBILITY), - LONG_INVISIBILITY(9, ArrowParticleColors.INVISIBILITY), - LEAPING(10, ArrowParticleColors.LEAPING), - LONG_LEAPING(11, ArrowParticleColors.LEAPING), - STRONG_LEAPING(12, ArrowParticleColors.LEAPING), - FIRE_RESISTANCE(13, ArrowParticleColors.FIRE_RESISTANCE), - LONG_FIRE_RESISTANCE(14, ArrowParticleColors.FIRE_RESISTANCE), - SWIFTNESS(15, ArrowParticleColors.SWIFTNESS), - LONG_SWIFTNESS(16, ArrowParticleColors.SWIFTNESS), - STRONG_SWIFTNESS(17, ArrowParticleColors.SWIFTNESS), - SLOWNESS(18, ArrowParticleColors.SLOWNESS), - LONG_SLOWNESS(19, ArrowParticleColors.SLOWNESS), - STRONG_SLOWNESS(43, ArrowParticleColors.SLOWNESS), - WATER_BREATHING(20, ArrowParticleColors.WATER_BREATHING), - LONG_WATER_BREATHING(21, ArrowParticleColors.WATER_BREATHING), - HEALING(22, ArrowParticleColors.HEALING), - STRONG_HEALING(23, ArrowParticleColors.HEALING), - HARMING(24, ArrowParticleColors.HARMING), - STRONG_HARMING(25, ArrowParticleColors.HARMING), - POISON(26, ArrowParticleColors.POISON), - LONG_POISON(27, ArrowParticleColors.POISON), - STRONG_POISON(28, ArrowParticleColors.POISON), - REGENERATION(29, ArrowParticleColors.REGENERATION), - LONG_REGENERATION(30, ArrowParticleColors.REGENERATION), - STRONG_REGENERATION(31, ArrowParticleColors.REGENERATION), - STRENGTH(32, ArrowParticleColors.STRENGTH), - LONG_STRENGTH(33, ArrowParticleColors.STRENGTH), - STRONG_STRENGTH(34, ArrowParticleColors.STRENGTH), - WEAKNESS(35, ArrowParticleColors.WEAKNESS), - LONG_WEAKNESS(36, ArrowParticleColors.WEAKNESS), - LUCK(2, ArrowParticleColors.NONE), // does not exist in Bedrock - TURTLE_MASTER(38, ArrowParticleColors.TURTLE_MASTER), - LONG_TURTLE_MASTER(39, ArrowParticleColors.TURTLE_MASTER), - STRONG_TURTLE_MASTER(40, ArrowParticleColors.TURTLE_MASTER), - SLOW_FALLING(41, ArrowParticleColors.SLOW_FALLING), - LONG_SLOW_FALLING(42, ArrowParticleColors.SLOW_FALLING); - - private static final TippedArrowPotion[] VALUES = values(); - - private final String javaIdentifier; - private final short bedrockId; - /** - * The Java color associated with this ID. - * Used for looking up Java arrow color entity metadata as Bedrock potion IDs, which is what is used for entities in Bedrock - */ - private final int javaColor; - - TippedArrowPotion(int bedrockId, ArrowParticleColors arrowParticleColor) { - this.javaIdentifier = "minecraft:" + this.name().toLowerCase(Locale.ENGLISH); - this.bedrockId = (short) bedrockId; - this.javaColor = arrowParticleColor.getColor(); - } - - 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) { - for (TippedArrowPotion potion : VALUES) { - if (potion.bedrockId == bedrockId) { - return potion; - } - } - return null; - } - - /** - * @param color the potion color to look up - * @return the tipped arrow potion that most closely resembles that color. - */ - public static @Nullable TippedArrowPotion getByJavaColor(int color) { - for (TippedArrowPotion potion : VALUES) { - if (potion.javaColor == color) { - return potion; - } - } - return null; - } - - private enum ArrowParticleColors { - NONE(-1), - NIGHT_VISION(2039713), - INVISIBILITY(8356754), - LEAPING(2293580), - FIRE_RESISTANCE(14981690), - SWIFTNESS(8171462), - SLOWNESS(5926017), - TURTLE_MASTER(7691106), - WATER_BREATHING(3035801), - HEALING(16262179), - HARMING(4393481), - POISON(5149489), - REGENERATION(13458603), - STRENGTH(9643043), - WEAKNESS(4738376), - LUCK(3381504), - SLOW_FALLING(16773073); - - @Getter - private final int color; - - ArrowParticleColors(int color) { - this.color = color; - } - } -} 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 84c3b1a39..c06a143ac 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 @@ -28,15 +28,13 @@ package org.geysermc.geyser.item.type; 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.inventory.item.Potion; 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.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); @@ -44,11 +42,11 @@ public class ArrowItem extends Item { @Override public @NonNull GeyserItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) { - TippedArrowPotion tippedArrowPotion = TippedArrowPotion.getByBedrockId(itemData.getDamage()); + Potion potion = Potion.getByTippedArrowDamage(itemData.getDamage()); GeyserItemStack itemStack = super.translateToJava(itemData, mapping, mappings); - if (tippedArrowPotion != null) { + if (potion != null) { itemStack = Items.TIPPED_ARROW.newItemStack(itemStack.getAmount(), itemStack.getComponents()); - PotionContents contents = new PotionContents(tippedArrowPotion.ordinal(), -1, Collections.emptyList()); + PotionContents contents = potion.toComponent(); itemStack.getOrCreateComponents().put(DataComponentType.POTION_CONTENTS, contents); } return itemStack; 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 db33bb584..d9e58eaf9 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 @@ -27,7 +27,7 @@ package org.geysermc.geyser.item.type; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.geysermc.geyser.GeyserImpl; -import org.geysermc.geyser.inventory.item.TippedArrowPotion; +import org.geysermc.geyser.inventory.item.Potion; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; @@ -44,11 +44,11 @@ public class TippedArrowItem extends ArrowItem { if (components != null) { PotionContents potionContents = components.get(DataComponentType.POTION_CONTENTS); if (potionContents != null) { - TippedArrowPotion tippedArrowPotion = TippedArrowPotion.of(potionContents.getPotionId()); - if (tippedArrowPotion != null) { + Potion potion = Potion.getByJavaId(potionContents.getPotionId()); + if (potion != null) { return ItemData.builder() .definition(mapping.getBedrockDefinition()) - .damage(tippedArrowPotion.getBedrockId()) + .damage(potion.tippedArrowId()) .count(count); } GeyserImpl.getInstance().getLogger().debug("Unknown Java potion (tipped arrow): " + potionContents.getPotionId()); From 3f8739a88fe3b00d8d54a9208fe4239d26dd710f Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Wed, 5 Jun 2024 16:56:44 -0400 Subject: [PATCH 059/233] New effects --- .../src/main/java/org/geysermc/geyser/util/EntityUtils.java | 6 ++++++ 1 file changed, 6 insertions(+) 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 d11c1f9e4..bfb70a4ed 100644 --- a/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java @@ -77,6 +77,12 @@ public final class EntityUtils { case BAD_OMEN -> 28; case HERO_OF_THE_VILLAGE -> 29; case DARKNESS -> 30; + case TRIAL_OMEN -> 31; + case WIND_CHARGED -> 32; + case WEAVING -> 33; + case OOZING -> 34; + case INFESTED -> 35; + case RAID_OMEN -> 36; default -> effect.ordinal() + 1; }; } From 8f5d1560a22bab61dea004b2d355c4d4e4e7f0fa Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Thu, 6 Jun 2024 18:20:24 -0400 Subject: [PATCH 060/233] Implement Bogged entity --- .../geyser/entity/EntityDefinitions.java | 6 ++ .../type/living/monster/BoggedEntity.java | 73 ++++++++++++++++++ .../type/living/monster/BreezeEntity.java | 44 +++++++++++ .../resources/bedrock/entity_identifiers.dat | Bin 8314 -> 8314 bytes 4 files changed, 123 insertions(+) create mode 100644 core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BoggedEntity.java create mode 100644 core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BreezeEntity.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 21cc526dd..76c65e9c8 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -63,6 +63,7 @@ public final class EntityDefinitions { public static final EntityDefinition BEE; public static final EntityDefinition BLAZE; public static final EntityDefinition BOAT; + public static final EntityDefinition BOGGED; public static final EntityDefinition CAMEL; public static final EntityDefinition CAT; public static final EntityDefinition CAVE_SPIDER; @@ -503,6 +504,11 @@ public final class EntityDefinitions { .height(0.9f).width(0.5f) .addTranslator(MetadataType.BYTE, BatEntity::setBatFlags) .build(); + BOGGED = EntityDefinition.inherited(BoggedEntity::new, mobEntityBase) + .type(EntityType.BOGGED) + .height(1.99f).width(0.6f) + .addTranslator(MetadataType.BOOLEAN, BoggedEntity::setSheared) + .build(); BLAZE = EntityDefinition.inherited(BlazeEntity::new, mobEntityBase) .type(EntityType.BLAZE) .height(1.8f).width(0.6f) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BoggedEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BoggedEntity.java new file mode 100644 index 000000000..806d58ed1 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BoggedEntity.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 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; + +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; +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.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; + +public class BoggedEntity extends AbstractSkeletonEntity { + private boolean sheared = false; + + public BoggedEntity(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 void setSheared(BooleanEntityMetadata entityMetadata) { + this.sheared = entityMetadata.getPrimitiveValue(); + setFlag(EntityFlag.SHEARED, this.sheared); + } + + @Override + protected @NonNull InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { + if (itemInHand.asItem() == Items.SHEARS && readyForShearing()) { + return InteractiveTag.SHEAR; + } + return super.testMobInteraction(hand, itemInHand); + } + + @Override + protected @NonNull InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) { + if (itemInHand.asItem() == Items.SHEARS && readyForShearing()) { + return InteractionResult.SUCCESS; + } + return super.mobInteract(hand, itemInHand); + } + + private boolean readyForShearing() { + return !this.sheared && this.isAlive(); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BreezeEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BreezeEntity.java new file mode 100644 index 000000000..25d466aaf --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BreezeEntity.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 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; + +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.Pose; + +import java.util.UUID; + +public class BreezeEntity extends MonsterEntity { + public BreezeEntity(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 void setPose(Pose pose) { + super.setPose(pose); + } +} diff --git a/core/src/main/resources/bedrock/entity_identifiers.dat b/core/src/main/resources/bedrock/entity_identifiers.dat index e7cdeb08e65d446bef173af7cea4bc56d5023df3..95d00c246abac44e32f992549d970a3e650fa440 100644 GIT binary patch delta 890 zcmX|9OGuPa6n5T^`~NflJe;?VlojFYpBWvSmouX?rm0~I3koVo7eZiQ8=;1T7OkS; z10yLCf@tMFvd9qH2t`D-ilJI&M9@aWI`>$v&b{ZJ`+eW}&e<+)msDqy!#X>Cd3OG) z^M(-fi6^lf8$rz>(B9h1xwDkJ5X<3wi@=rW z06xVBuo_L#{TZ%@1TMAa@tJDnpNACPMuEHWK?K|4Xn1{C@d$KAGtBoZ(t{_FEG9h` zye0nmNFO>Qc{IY~s5u25gojWFPuANkxMmjEiY2&o%`adLC;z86LVT1Bs39FsgB3J9 z8fw8bS9b(Q&=C~)5h!3eFp4$5g6TjSt3GNlkmLBVIfpyVc_y7`9>T7_LUn^!@DH)z zqCd+5|M>c-{uCA{rhLQL^-94CUU?Ik^B$*v0%>oCF@Jh;^tXyB&lrN90esNPjCEhj z;_@d`wZAIO9sA+b$4xx$s3jBELU37xCLN%;Q_M=+K0Md#cXkcGx=i z6)akFoLf>73^k>c5vKE|807nsNE4R88PQ7^d2Bi>EM?r;wMRn(a>~uf;9^vR-NET@ zdzG1YZ8}%4+X}c9O5mib;3l0bmL$yT30gV@?~O+#lG`{28>Qv0*6b;XR$ooYm8#F{ zB&Eziw@pcsChGd0Axp-tfBqGD`G&0>5=(kAVM?PADskiIj5^C%G4S(_NyQ6GKR?YF mbW&9$TG|e4fzcXaX=Ryw$unuyCUs<~Nu|D(M9JK4X!;8-wi;dl delta 925 zcmX|AOK1~e5N^^WP4e$1n`iTG)Psn&+07=g-8`G5r7xtV2T#R7oD9-56k>J^M5n*&3yk}ZLcP~J6w*r za~I|om)uva@Wmq7jyLcyAwiF4(6$Qvis^Xc7dV{Ou^Scm){{XsBycFD;YUQ^QSvzM zI_#KDRBJs>xDDa)9@hsh zJi#5Atk!z=S>>Y@ypEJ{Eu!K|K%f*cINdX1ZL%_a^#jb`?q2q7$O0B$j{W9j-gft~ ze_a`5pV{v9Zi-W#A;u_}S1KI)6K*n%cVUfaRk^>RaDk>S&>23-vG*a0g(fgY*35C+ zpT*IKO)J}1kLqIBOZ< z`K213on>cmMzZ From c3994a677be4fb3065db2151c71c24f53faa7308 Mon Sep 17 00:00:00 2001 From: RK_01 <50594595+RaphiMC@users.noreply.github.com> Date: Fri, 7 Jun 2024 00:54:33 +0200 Subject: [PATCH 061/233] Override forward-hostname setting if ViaProxy wildcard domain handling is enabled (#4720) --- .../viaproxy/GeyserViaProxyConfiguration.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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 bf9d6816c..1b82e9f67 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 @@ -27,6 +27,7 @@ package org.geysermc.geyser.platform.viaproxy; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import net.raphimc.vialegacy.api.LegacyProtocolVersion; import net.raphimc.viaproxy.ViaProxy; +import net.raphimc.viaproxy.protocoltranslator.viaproxy.ViaProxyConfig; import org.geysermc.geyser.configuration.GeyserJacksonConfiguration; import java.io.File; @@ -50,4 +51,16 @@ public class GeyserViaProxyConfiguration extends GeyserJacksonConfiguration { return interval; } + @Override + public RemoteConfiguration getRemote() { + return new RemoteConfiguration() { + + @Override + public boolean isForwardHost() { + return super.isForwardHost() || !ViaProxy.getConfig().getWildcardDomainHandling().equals(ViaProxyConfig.WildcardDomainHandling.NONE); + } + + }; + } + } From 29c9515d55b1bf4dc734b935f905806ca0463414 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Thu, 6 Jun 2024 20:28:38 -0400 Subject: [PATCH 062/233] Re-implement jukebox songs --- .../geyser/item/enchantment/Enchantment.java | 18 ++-- .../geysermc/geyser/level/JukeboxSong.java | 40 +++++++++ .../geyser/session/cache/RegistryCache.java | 3 + .../geyser/session/cache/WorldCache.java | 16 ++++ .../java/level/JavaLevelEventTranslator.java | 90 +++++++++++++------ .../translator/text/MessageTranslator.java | 15 ++++ .../org/geysermc/geyser/util/SoundUtils.java | 3 +- 7 files changed, 141 insertions(+), 44 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/level/JukeboxSong.java diff --git a/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java b/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java index 8d1d92f6c..468b88e87 100644 --- a/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java +++ b/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java @@ -27,13 +27,15 @@ package org.geysermc.geyser.item.enchantment; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtMap; -import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.item.BedrockEnchantment; import org.geysermc.geyser.session.cache.tags.EnchantmentTag; import org.geysermc.geyser.session.cache.tags.ItemTag; +import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; -import java.util.*; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; /** * @param description only populated if {@link #bedrockEnchantment()} is not null. @@ -59,7 +61,7 @@ public record Enchantment(String identifier, String exclusiveSet = data.getString("exclusive_set", null); EnchantmentTag exclusiveSetTag = exclusiveSet == null ? null : EnchantmentTag.ALL_ENCHANTMENT_TAGS.get(exclusiveSet.substring(1)); BedrockEnchantment bedrockEnchantment = BedrockEnchantment.getByJavaIdentifier(entry.getId()); - String description = bedrockEnchantment == null ? readDescription(data) : null; + String description = bedrockEnchantment == null ? MessageTranslator.deserializeDescription(data) : null; return new Enchantment(entry.getId(), effects, ItemTag.ALL_ITEM_TAGS.get(supportedItems), maxLevel, description, anvilCost, exclusiveSetTag, bedrockEnchantment); @@ -74,14 +76,4 @@ public record Enchantment(String identifier, } return Set.copyOf(components); // Also ensures any empty sets are consolidated } - - private static String readDescription(NbtMap tag) { - NbtMap description = tag.getCompound("description"); - String translate = description.getString("translate", null); - if (translate == null) { - GeyserImpl.getInstance().getLogger().debug("Don't know how to read description! " + tag); - return ""; - } - return translate; - } } diff --git a/core/src/main/java/org/geysermc/geyser/level/JukeboxSong.java b/core/src/main/java/org/geysermc/geyser/level/JukeboxSong.java new file mode 100644 index 000000000..fd6ce693d --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/JukeboxSong.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 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.level; + +import org.cloudburstmc.nbt.NbtMap; +import org.geysermc.geyser.translator.text.MessageTranslator; +import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; + +public record JukeboxSong(String soundEvent, String description) { + + public static JukeboxSong read(RegistryEntry entry) { + NbtMap data = entry.getData(); + String soundEvent = data.getString("sound_event"); + String description = MessageTranslator.deserializeDescription(data); + return new JukeboxSong(soundEvent, description); + } +} 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 fe970ee2b..266a0a418 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 @@ -40,6 +40,7 @@ import org.geysermc.geyser.inventory.item.BannerPattern; import org.geysermc.geyser.inventory.recipe.TrimRecipe; import org.geysermc.geyser.item.enchantment.Enchantment; import org.geysermc.geyser.level.JavaDimension; +import org.geysermc.geyser.level.JukeboxSong; import org.geysermc.geyser.level.PaintingType; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.registry.JavaRegistry; @@ -76,6 +77,7 @@ public final class RegistryCache { register("chat_type", cache -> cache.chatTypes, ($, entry) -> TextDecoration.readChatType(entry)); register("dimension_type", cache -> cache.dimensions, ($, entry) -> JavaDimension.read(entry)); register("enchantment", cache -> cache.enchantments, ($, entry) -> Enchantment.read(entry)); + register("jukebox_song", cache -> cache.jukeboxSongs, ($, entry) -> JukeboxSong.read(entry)); register("painting_variant", cache -> cache.paintings, ($, entry) -> PaintingType.getByName(entry.getId())); register("trim_material", cache -> cache.trimMaterials, TrimRecipe::readTrimMaterial); register("trim_pattern", cache -> cache.trimPatterns, TrimRecipe::readTrimPattern); @@ -115,6 +117,7 @@ public final class RegistryCache { */ private final JavaRegistry dimensions = new SimpleJavaRegistry<>(); private final JavaRegistry enchantments = new SimpleJavaRegistry<>(); + private final JavaRegistry jukeboxSongs = new SimpleJavaRegistry<>(); private final JavaRegistry paintings = new SimpleJavaRegistry<>(); private final JavaRegistry trimMaterials = new SimpleJavaRegistry<>(); private final JavaRegistry trimPatterns = new SimpleJavaRegistry<>(); 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 44ec7a6b9..8eb715560 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 @@ -28,8 +28,10 @@ package org.geysermc.geyser.session.cache; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntMaps; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.Getter; import lombok.Setter; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.packet.SetTitlePacket; import org.geysermc.geyser.scoreboard.Scoreboard; @@ -39,6 +41,7 @@ import org.geysermc.geyser.util.ChunkUtils; import org.geysermc.mcprotocollib.protocol.data.game.setting.Difficulty; import java.util.Iterator; +import java.util.Map; public final class WorldCache { private final GeyserSession session; @@ -61,6 +64,8 @@ public final class WorldCache { private int currentSequence; private final Object2IntMap unverifiedPredictions = new Object2IntOpenHashMap<>(1); + private final Map activeRecords = new Object2ObjectOpenHashMap<>(1); // Assume the average player won't be listening to many records + @Getter @Setter private boolean editingSignOnFront; @@ -185,4 +190,15 @@ public final class WorldCache { } } } + + public void addActiveRecord(Vector3i pos, String bedrockPlaySound) { + this.activeRecords.put(pos, bedrockPlaySound); + } + + // Implementation note: positions aren't removed unless the server calls, but this seems to match 1.21 Java + // client behavior. + @Nullable + public String removeActiveRecord(Vector3i pos) { + return this.activeRecords.remove(pos); + } } \ No newline at end of file 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 cb8a8e60f..ef0329209 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,28 +25,27 @@ package org.geysermc.geyser.translator.protocol.java.level; -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; 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; -import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket; -import org.cloudburstmc.protocol.bedrock.packet.TextPacket; +import org.cloudburstmc.protocol.bedrock.packet.*; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.level.JukeboxSong; import org.geysermc.geyser.registry.Registries; +import org.geysermc.geyser.registry.type.SoundMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.translator.level.event.LevelEventTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.geyser.util.SoundUtils; +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 java.util.Collections; -import java.util.Locale; import java.util.Set; @Translator(packet = ClientboundLevelEventPacket.class) @@ -60,23 +59,48 @@ public class JavaLevelEventTranslator extends PacketTranslator { - LevelSoundEventPacket levelSoundEvent = new LevelSoundEventPacket(); - levelSoundEvent.setIdentifier(""); - levelSoundEvent.setSound(SoundEvent.STOP_RECORD); - levelSoundEvent.setPosition(pos); - levelSoundEvent.setRelativeVolumeDisabled(false); - levelSoundEvent.setExtraData(-1); - levelSoundEvent.setBabySound(false); - session.sendUpstreamPacket(levelSoundEvent); + String bedrockSound = session.getWorldCache().removeActiveRecord(origin); + if (bedrockSound == null) { + // Vanilla record + LevelSoundEventPacket levelSoundEvent = new LevelSoundEventPacket(); + levelSoundEvent.setIdentifier(""); + levelSoundEvent.setSound(SoundEvent.STOP_RECORD); + levelSoundEvent.setPosition(pos); + levelSoundEvent.setRelativeVolumeDisabled(false); + levelSoundEvent.setExtraData(-1); + levelSoundEvent.setBabySound(false); + session.sendUpstreamPacket(levelSoundEvent); + } else { + // Custom record + StopSoundPacket stopSound = new StopSoundPacket(); + stopSound.setSoundName(bedrockSound); + session.sendUpstreamPacket(stopSound); + } return; } default -> { 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 3507567be..152bf4160 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 @@ -35,6 +35,7 @@ import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.kyori.adventure.text.serializer.legacy.CharacterAndFormat; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; +import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.protocol.bedrock.packet.TextPacket; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.session.GeyserSession; @@ -424,6 +425,20 @@ public class MessageTranslator { return new String(newChars, 0, count - (whitespacesCount > 0 ? 1 : 0)).trim(); } + /** + * Deserialize an NbtMap provided from a registry into a string. + */ + // This may be a Component in the future. + public static String deserializeDescription(NbtMap tag) { + NbtMap description = tag.getCompound("description"); + String translate = description.getString("translate", null); + if (translate == null) { + GeyserImpl.getInstance().getLogger().debug("Don't know how to read description! " + tag); + return ""; + } + return translate; + } + public static void init() { // no-op } 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 7559347e9..524d241db 100644 --- a/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java @@ -33,7 +33,6 @@ import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket; import org.cloudburstmc.protocol.bedrock.packet.PlaySoundPacket; import org.geysermc.geyser.GeyserImpl; -import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; @@ -52,7 +51,7 @@ public final class SoundUtils { * @param sound the sound name * @return a sound event from the given sound */ - private static @Nullable SoundEvent toSoundEvent(String sound) { + public static @Nullable SoundEvent toSoundEvent(String sound) { try { return SoundEvent.valueOf(sound.toUpperCase(Locale.ROOT).replace(".", "_")); } catch (Exception ex) { From 79bcc790ce6c4670569f78a819a7eab4f3c613eb Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Thu, 6 Jun 2024 20:30:55 -0400 Subject: [PATCH 063/233] Remove Registries.RECORDS --- .../geyser/registry/IntMappedRegistry.java | 122 ------------------ .../geysermc/geyser/registry/Registries.java | 6 - .../populator/ItemRegistryPopulator.java | 5 - 3 files changed, 133 deletions(-) delete mode 100644 core/src/main/java/org/geysermc/geyser/registry/IntMappedRegistry.java diff --git a/core/src/main/java/org/geysermc/geyser/registry/IntMappedRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/IntMappedRegistry.java deleted file mode 100644 index 981ed0f8c..000000000 --- a/core/src/main/java/org/geysermc/geyser/registry/IntMappedRegistry.java +++ /dev/null @@ -1,122 +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.registry; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.geysermc.geyser.registry.loader.RegistryLoader; - -import java.util.function.Supplier; - -/** - * A mapped registry with an integer as the key. This class is designed to minimize the need for boxing/unboxing keys. - * - * @param the value - */ -public class IntMappedRegistry extends AbstractMappedRegistry> { - protected IntMappedRegistry(I input, RegistryLoader> registryLoader) { - super(input, registryLoader); - } - - /** - * Returns the value registered by the given integer. - * - * @param i the integer - * @return the value registered by the given integer. - */ - public V get(int i) { - return this.mappings.get(i); - } - - @Nullable - @Override - @Deprecated - public V get(Integer key) { - return super.get(key); - } - - /** - * Returns the value registered by the given key or the default value - * specified if null. - * - * @param i the key - * @param defaultValue the default value - * @return the value registered by the given key or the default value - * specified if null. - */ - public V getOrDefault(int i, V defaultValue) { - return this.mappings.getOrDefault(i, defaultValue); - } - - @Override - @Deprecated - public V getOrDefault(Integer key, V defaultValue) { - return super.getOrDefault(key, defaultValue); - } - - /** - * Registers a new value into this registry with the given key. - * - * @param i the key - * @param value the value - * @return a new value into this registry with the given key. - */ - public V register(int i, V value) { - return this.mappings.put(i, value); - } - - @Override - @Deprecated - public V register(Integer key, V value) { - return super.register(key, value); - } - - /** - * Creates a new integer mapped registry with the given {@link RegistryLoader}. The - * input type is not specified here, meaning the loader return type is either - * predefined, or the registry is populated at a later point. - * - * @param registryLoader the registry loader - * @param the input - * @param the map value - * @return a new registry with the given RegistryLoader - */ - public static IntMappedRegistry create(RegistryLoader> registryLoader) { - return new IntMappedRegistry<>(null, registryLoader); - } - - /** - * Creates a new integer mapped registry with the given {@link RegistryLoader} and input. - * - * @param registryLoader the registry loader - * @param the input - * @param the map value - * @return a new registry with the given RegistryLoader supplier - */ - public static IntMappedRegistry create(I input, Supplier>> registryLoader) { - return new IntMappedRegistry<>(input, registryLoader.get()); - } -} 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 c6980efd1..7815768ef 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/Registries.java +++ b/core/src/main/java/org/geysermc/geyser/registry/Registries.java @@ -149,12 +149,6 @@ public final class Registries { */ public static final VersionedRegistry> RECIPES = VersionedRegistry.create(RegistryLoaders.empty(Int2ObjectOpenHashMap::new)); - /** - * A mapped registry holding the available records, with the ID of the record being the key, and the {@link org.cloudburstmc.protocol.bedrock.data.SoundEvent} - * as the value. - */ - public static final IntMappedRegistry RECORDS = IntMappedRegistry.create(RegistryLoaders.empty(Int2ObjectOpenHashMap::new)); - /** * A mapped registry holding {@link ResourcePack}'s with the pack uuid as keys. */ 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 8f515c1cb..e19066462 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,7 +41,6 @@ import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.nbt.NbtUtils; import org.cloudburstmc.protocol.bedrock.codec.v671.Bedrock_v671; import org.cloudburstmc.protocol.bedrock.codec.v685.Bedrock_v685; -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; @@ -458,10 +457,6 @@ public class ItemRegistryPopulator { if (javaItem.javaIdentifier().contains("bucket") && !javaItem.javaIdentifier().contains("milk")) { buckets.add(definition); - } 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_" + - mapping.getBedrockIdentifier().replace("minecraft:music_disc_", "").toUpperCase(Locale.ENGLISH))); } mappings.add(mapping); From b7931f8d704f638273bb13215df0077fd144e049 Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Thu, 6 Jun 2024 23:34:06 +0200 Subject: [PATCH 064/233] Update protocol to suppress packet warnings --- 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 1995a6ada..9ff1f3afd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,7 @@ 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" -protocol = "3.0.0.Beta2-20240520.153053-5" +protocol = "3.0.0.Beta2-20240606.172607-7" raknet = "1.0.0.CR3-20240416.144209-1" mcauthlib = "e5b0bcc" mcprotocollib = "1.20.6-2-20240520.030045-8" From 9b776b5321b0f98bd5ccbda9a692770f0c52e85f Mon Sep 17 00:00:00 2001 From: RK_01 <50594595+RaphiMC@users.noreply.github.com> Date: Fri, 7 Jun 2024 19:26:59 +0200 Subject: [PATCH 065/233] Fixed remote config being reset everytime when accessed on Geyser-ViaProxy (#4722) --- .../viaproxy/GeyserViaProxyConfiguration.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 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 1b82e9f67..afc46fa6a 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 @@ -34,8 +34,16 @@ import java.io.File; import java.nio.file.Path; @JsonIgnoreProperties(ignoreUnknown = true) +@SuppressWarnings("FieldMayBeFinal") // Jackson requires that the fields are not final public class GeyserViaProxyConfiguration extends GeyserJacksonConfiguration { + private RemoteConfiguration remote = new RemoteConfiguration() { + @Override + public boolean isForwardHost() { + return super.isForwardHost() || !ViaProxy.getConfig().getWildcardDomainHandling().equals(ViaProxyConfig.WildcardDomainHandling.NONE); + } + }; + @Override public Path getFloodgateKeyPath() { return new File(GeyserViaProxyPlugin.ROOT_FOLDER, this.getFloodgateKeyFile()).toPath(); @@ -53,14 +61,7 @@ public class GeyserViaProxyConfiguration extends GeyserJacksonConfiguration { @Override public RemoteConfiguration getRemote() { - return new RemoteConfiguration() { - - @Override - public boolean isForwardHost() { - return super.isForwardHost() || !ViaProxy.getConfig().getWildcardDomainHandling().equals(ViaProxyConfig.WildcardDomainHandling.NONE); - } - - }; + return this.remote; } } From 8ae1150c8026af625bd39143b50f3b9a08acdfed Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Fri, 7 Jun 2024 19:47:21 +0200 Subject: [PATCH 066/233] Remove unused lectern code in ModWorldManager, fix spelling error in SessionLoginEvent --- .../api/event/bedrock/SessionLoginEvent.java | 6 +-- .../mod/world/GeyserModWorldManager.java | 38 ------------------- 2 files changed, 3 insertions(+), 41 deletions(-) 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 522562d11..86a5ec6f8 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 @@ -36,7 +36,7 @@ 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. + * 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 { @@ -99,9 +99,9 @@ public final class SessionLoginEvent extends ConnectionEvent implements Cancella } /** - * Gets the {@link RemoteServer} the section will attempt to connect to. + * Gets the {@link RemoteServer} the session will attempt to connect to. * - * @return the {@link RemoteServer} the section will attempt to connect to. + * @return the {@link RemoteServer} the session will attempt to connect to. */ public @NonNull RemoteServer remoteServer() { return this.remoteServer; 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 7aac684bb..5543dbcee 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 @@ -26,7 +26,6 @@ package org.geysermc.geyser.platform.mod.world; 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.core.RegistryAccess; @@ -34,10 +33,7 @@ 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.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; @@ -63,7 +59,6 @@ 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) { @@ -169,39 +164,6 @@ public class GeyserModWorldManager extends GeyserWorldManager { return server.getPlayerList().getPlayer(session.getPlayerEntity().getUuid()); } - 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; - } - } - - 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(GeyserModWorldManager::fromComponent) - .toList(); - } else { - WritableBookContent writableBookContent = itemStack.get(DataComponents.WRITABLE_BOOK_CONTENT); - if (writableBookContent == null) { - return List.of(); - } - return writableBookContent.pages().stream() - .map(Filterable::raw) - .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()); From 007ecb4363dcb7ca0f396732b4440f274d5b9842 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sun, 9 Jun 2024 15:06:39 -0400 Subject: [PATCH 067/233] Ensure custom blocks can be represented at any index --- .../java/org/geysermc/geyser/item/Items.java | 8 +------- .../geyser/registry/ListRegistry.java | 20 +++++++++++++++++++ .../geysermc/geyser/registry/Registries.java | 5 ++++- .../populator/BlockRegistryPopulator.java | 3 +-- 4 files changed, 26 insertions(+), 10 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 8c271a7bb..03f044068 100644 --- a/core/src/main/java/org/geysermc/geyser/item/Items.java +++ b/core/src/main/java/org/geysermc/geyser/item/Items.java @@ -30,8 +30,6 @@ import org.geysermc.geyser.item.type.*; import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.registry.Registries; -import java.util.Collections; - import static org.geysermc.geyser.item.type.Item.builder; /** @@ -1378,11 +1376,7 @@ public final class Items { public static T register(T item, int id) { item.setJavaId(id); - // This makes sure that the array is large enough to put the java item at the correct location - if (Registries.JAVA_ITEMS.get().size() <= id) { - Registries.JAVA_ITEMS.get().addAll(Collections.nCopies(id - Registries.JAVA_ITEMS.get().size() + 1, AIR)); - } - Registries.JAVA_ITEMS.get().set(id, item); + Registries.JAVA_ITEMS.registerWithAnyIndex(id, item, AIR); Registries.JAVA_ITEM_IDENTIFIERS.register(item.javaIdentifier(), item); return item; } diff --git a/core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java index 34a78c370..2070d67ae 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java +++ b/core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java @@ -29,6 +29,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.registry.loader.RegistryLoader; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.function.Supplier; @@ -94,6 +95,25 @@ public class ListRegistry extends Registry> { return this.mappings.set(index, value); } + /** + * Registers a new value into this registry with the given index, even if this value would normally be outside + * the range of a list. + * + * @param index the index + * @param value the value + * @param defaultValue the default value to fill empty spaces in the registry with. + * @return a new value into this registry with the given index. + */ + public M registerWithAnyIndex(int index, M value, M defaultValue) { + if (this.frozen) { + throw new IllegalStateException("Registry should not be modified after frozen!"); + } + if (this.mappings.size() <= index) { + this.mappings.addAll(Collections.nCopies(index - this.mappings.size() + 1, defaultValue)); + } + return this.mappings.set(index, value); + } + /** * Mark this registry as unsuitable for new additions. The backing list will then be optimized for storage. */ 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 54d013140..b509d6ac0 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/Registries.java +++ b/core/src/main/java/org/geysermc/geyser/registry/Registries.java @@ -127,7 +127,10 @@ public final class Registries { */ public static final PacketTranslatorRegistry JAVA_PACKET_TRANSLATORS = PacketTranslatorRegistry.create(); - public static final SimpleRegistry> JAVA_ITEMS = SimpleRegistry.create(RegistryLoaders.empty(ArrayList::new)); + /** + * A registry containing all Java items ordered by their network ID. + */ + public static final ListRegistry JAVA_ITEMS = ListRegistry.create(RegistryLoaders.empty(ArrayList::new)); public static final SimpleMappedRegistry JAVA_ITEM_IDENTIFIERS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new)); 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 6b856c509..a8fb0001d 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 @@ -213,7 +213,6 @@ public final class BlockRegistryPopulator { GeyserBedrockBlock[] javaToBedrockBlocks = new GeyserBedrockBlock[JAVA_BLOCKS_SIZE]; GeyserBedrockBlock[] javaToVanillaBedrockBlocks = new GeyserBedrockBlock[JAVA_BLOCKS_SIZE]; - //List javaToBedrockIdentifiers = new ArrayList<>(BlockRegistries.JAVA_BLOCKS.get().size()); var javaToBedrockIdentifiers = new Int2ObjectOpenHashMap(); Block lastBlockSeen = null; @@ -456,7 +455,7 @@ public final class BlockRegistryPopulator { }; block.setJavaId(javaBlockState.stateGroupId()); - BlockRegistries.JAVA_BLOCKS.get().add(javaBlockState.stateGroupId(), block); //TODO don't allow duplicates, allow blanks + BlockRegistries.JAVA_BLOCKS.registerWithAnyIndex(javaBlockState.stateGroupId(), block, Blocks.AIR); BlockRegistries.JAVA_IDENTIFIER_TO_ID.register(javaId, stateRuntimeId); BlockRegistries.BLOCK_STATES.register(stateRuntimeId, new BlockState(block, stateRuntimeId)); } From e9e364636a8774cdbe1244b46a81eec52e6700ee Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sun, 9 Jun 2024 15:44:29 -0400 Subject: [PATCH 068/233] New potion effects --- .../geyser/registry/loader/PotionMixRegistryLoader.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 0eec7cdb6..eae4e2bea 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,7 +27,6 @@ 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; @@ -75,6 +74,11 @@ public class PotionMixRegistryLoader implements RegistryLoader inputs = List.of( getNonNull(mappings, Items.POTION), From ae6059bdc3c467f39d7c8a7094d897c0e08a1263 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sun, 9 Jun 2024 16:57:51 -0400 Subject: [PATCH 069/233] Implement wind charges --- .../geyser/entity/EntityDefinitions.java | 16 ++++++ .../entity/type/AbstractWindChargeEntity.java | 53 ++++++++++++++++++ .../geyser/session/GeyserSession.java | 1 + .../java/level/JavaExplodeTranslator.java | 56 ++++++++++++------- .../level/JavaLevelParticlesTranslator.java | 5 +- 5 files changed, 108 insertions(+), 23 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/entity/type/AbstractWindChargeEntity.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 76c65e9c8..a7c2d6ca6 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,8 @@ package org.geysermc.geyser.entity; +import org.geysermc.geyser.entity.type.AbstractWindChargeEntity; +import org.geysermc.geyser.entity.factory.EntityFactory; 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; @@ -64,6 +66,7 @@ public final class EntityDefinitions { public static final EntityDefinition BLAZE; public static final EntityDefinition BOAT; public static final EntityDefinition BOGGED; + public static final EntityDefinition BREEZE_WIND_CHARGE; public static final EntityDefinition CAMEL; public static final EntityDefinition CAT; public static final EntityDefinition CAVE_SPIDER; @@ -166,6 +169,7 @@ public final class EntityDefinitions { public static final EntityDefinition VINDICATOR; public static final EntityDefinition WANDERING_TRADER; public static final EntityDefinition WARDEN; + public static final EntityDefinition WIND_CHARGE; public static final EntityDefinition WITCH; public static final EntityDefinition WITHER; public static final EntityDefinition WITHER_SKELETON; @@ -376,6 +380,18 @@ public final class EntityDefinitions { .heightAndWidth(0.25f) .build(); + EntityFactory windChargeSupplier = AbstractWindChargeEntity::new; + BREEZE_WIND_CHARGE = EntityDefinition.inherited(windChargeSupplier, entityBase) + .type(EntityType.BREEZE_WIND_CHARGE) + .identifier("minecraft:breeze_wind_charge_projectile") + .heightAndWidth(0.3125f) + .build(); + WIND_CHARGE = EntityDefinition.inherited(windChargeSupplier, entityBase) + .type(EntityType.WIND_CHARGE) + .identifier("minecraft:wind_charge_projectile") + .heightAndWidth(0.3125f) + .build(); + EntityDefinition abstractArrowBase = EntityDefinition.inherited(AbstractArrowEntity::new, entityBase) .addTranslator(MetadataType.BYTE, AbstractArrowEntity::setArrowFlags) .addTranslator(null) // "Piercing level" diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/AbstractWindChargeEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/AbstractWindChargeEntity.java new file mode 100644 index 000000000..5678c3af4 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/entity/type/AbstractWindChargeEntity.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 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; + +import org.cloudburstmc.math.vector.Vector3f; +import org.geysermc.geyser.entity.EntityDefinition; +import org.geysermc.geyser.session.GeyserSession; + +import java.util.UUID; + +/** + * Note that, as of 1.21, a wind charge entity does not actually implement the thrown item. We're just reusing + * the "hide until far away" aspect. + */ +public class AbstractWindChargeEntity extends ThrowableItemEntity { + public AbstractWindChargeEntity(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 void tick() { + super.tick(); + } + + @Override + protected float getDrag() { + // Always, even in water. As of 1.21. + return 1f; + } +} 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 ae5e1d338..b8e617fbb 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -1047,6 +1047,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Override public void packetReceived(Session session, Packet packet) { + System.out.println(packet); Registries.JAVA_PACKET_TRANSLATORS.translate(packet.getClass(), packet, GeyserSession.this); } 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 496f5982d..85107d637 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,22 +25,24 @@ package org.geysermc.geyser.translator.protocol.java.level; -import org.geysermc.geyser.level.block.type.Block; -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; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; -import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.packet.LevelEventGenericPacket; -import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket; import org.cloudburstmc.protocol.bedrock.packet.SetEntityMotionPacket; -import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.type.Block; 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.geyser.util.SoundUtils; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.ExplosionInteraction; +import org.geysermc.mcprotocollib.protocol.data.game.level.particle.Particle; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundExplodePacket; + +import java.util.concurrent.ThreadLocalRandom; @Translator(packet = ClientboundExplodePacket.class) public class JavaExplodeTranslator extends PacketTranslator { @@ -56,27 +58,39 @@ public class JavaExplodeTranslator extends PacketTranslator createParticle(GeyserSession session, Particle particle) { + public static @Nullable Function createParticle(GeyserSession session, Particle particle) { switch (particle.getType()) { case BLOCK -> { int blockState = session.getBlockMappings().getBedrockBlockId(((BlockParticleData) particle.getData()).getBlockState()); @@ -177,6 +177,7 @@ public class JavaLevelParticlesTranslator extends PacketTranslator { ParticleMapping particleMapping = Registries.PARTICLES.get(particle.getType()); + System.out.println(particle.getType() + " " + particleMapping); if (particleMapping == null) { //TODO ensure no particle can be null return null; } @@ -205,7 +206,7 @@ public class JavaLevelParticlesTranslator extends PacketTranslator Date: Sun, 9 Jun 2024 16:58:26 -0400 Subject: [PATCH 070/233] oooops --- .../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 b8e617fbb..ae5e1d338 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -1047,7 +1047,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Override public void packetReceived(Session session, Packet packet) { - System.out.println(packet); Registries.JAVA_PACKET_TRANSLATORS.translate(packet.getClass(), packet, GeyserSession.this); } From edee5e7a8e61b818c506428f6f9e2da942285fa5 Mon Sep 17 00:00:00 2001 From: RK_01 <50594595+RaphiMC@users.noreply.github.com> Date: Mon, 10 Jun 2024 01:43:10 +0200 Subject: [PATCH 071/233] Add builtin server transfer support for ViaProxy (#4723) --- .../viaproxy/GeyserViaProxyPlugin.java | 5 +- .../GeyserServerTransferListener.java | 62 +++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/listener/GeyserServerTransferListener.java 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 30404e705..bdc80335a 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 @@ -37,6 +37,7 @@ 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.event.EventRegistrar; import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.command.GeyserCommandManager; @@ -44,6 +45,7 @@ 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.viaproxy.listener.GeyserServerTransferListener; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.util.FileUtils; @@ -57,7 +59,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.UUID; -public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserBootstrap { +public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserBootstrap, EventRegistrar { public static final File ROOT_FOLDER = new File(PluginManager.PLUGINS_DIR, "Geyser"); @@ -120,6 +122,7 @@ public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserBootst } this.geyser = GeyserImpl.load(PlatformType.VIAPROXY, this); + this.geyser.eventBus().register(this, new GeyserServerTransferListener()); LoopbackUtil.checkAndApplyLoopback(this.logger); } diff --git a/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/listener/GeyserServerTransferListener.java b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/listener/GeyserServerTransferListener.java new file mode 100644 index 000000000..64b3cc56e --- /dev/null +++ b/bootstrap/viaproxy/src/main/java/org/geysermc/geyser/platform/viaproxy/listener/GeyserServerTransferListener.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 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.platform.viaproxy.listener; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.common.net.HostAndPort; +import org.geysermc.event.PostOrder; +import org.geysermc.event.subscribe.Subscribe; +import org.geysermc.geyser.api.event.bedrock.SessionLoginEvent; +import org.geysermc.geyser.api.event.java.ServerTransferEvent; +import org.geysermc.geyser.session.GeyserSession; + +import java.util.Map; +import java.util.concurrent.TimeUnit; + +public class GeyserServerTransferListener { + + private final Cache> cookieStorages = CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build(); + + @Subscribe(postOrder = PostOrder.FIRST) + private void onServerTransfer(final ServerTransferEvent event) { + this.cookieStorages.put(event.connection().xuid(), event.cookies()); + final GeyserSession geyserSession = (GeyserSession) event.connection(); + final HostAndPort hostAndPort = HostAndPort.fromString(geyserSession.getClientData().getServerAddress()).withDefaultPort(19132); + event.bedrockHost(hostAndPort.getHost()); + event.bedrockPort(hostAndPort.getPort()); + } + + @Subscribe(postOrder = PostOrder.FIRST) + private void onSessionLogin(final SessionLoginEvent event) { + final Map cookies = this.cookieStorages.asMap().remove(event.connection().xuid()); + if (cookies != null) { + event.cookies(cookies); + event.transferring(true); + } + } + +} From 02179a798f12eaf5791e6d89cc95cfa0bf68d99a Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Mon, 10 Jun 2024 16:53:14 -0400 Subject: [PATCH 072/233] You shall compile! --- .../translator/protocol/java/level/JavaExplodeTranslator.java | 2 +- .../protocol/java/level/JavaLevelEventTranslator.java | 1 - .../protocol/java/level/JavaLevelParticlesTranslator.java | 1 - core/src/main/resources/mappings | 2 +- gradle/libs.versions.toml | 4 ++-- 5 files changed, 4 insertions(+), 6 deletions(-) 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 85107d637..f840b8143 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 @@ -74,7 +74,7 @@ public class JavaExplodeTranslator extends PacketTranslator { ParticleMapping particleMapping = Registries.PARTICLES.get(particle.getType()); - System.out.println(particle.getType() + " " + particleMapping); if (particleMapping == null) { //TODO ensure no particle can be null return null; } diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings index 1f1d5ce8c..54705bcd2 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 1f1d5ce8c482dac142f13e95e19368e3f36de144 +Subproject commit 54705bcd2bcba830267efbb1fbfd4e52972c40f7 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 089cab44f..afd001220 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ websocket = "1.5.1" protocol = "3.0.0.Beta2-20240606.172607-7" raknet = "1.0.0.CR3-20240416.144209-1" mcauthlib = "e5b0bcc" -mcprotocollib = "1.21-SNAPSHOT" +mcprotocollib = "784e91c" 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 = "org.geysermc.mcprotocollib", name = "protocol", 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 538e9f4dd6bb2d7d9e00fae73e834f9a93b572c1 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Mon, 10 Jun 2024 17:04:43 -0400 Subject: [PATCH 073/233] Properly remove SnowCollision --- .../translator/collision/BlockCollision.java | 2 +- .../translator/collision/SnowCollision.java | 89 ------------------- 2 files changed, 1 insertion(+), 90 deletions(-) delete mode 100644 core/src/main/java/org/geysermc/geyser/translator/collision/SnowCollision.java 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 a2615deb1..2481028a4 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 @@ -61,7 +61,7 @@ public class BlockCollision { } /** - * Overridden in classes like SnowCollision and GrassPathCollision when correction code needs to be run before the + * Overridden in classes like GrassPathCollision when correction code needs to be run before the * main correction */ public void beforeCorrectPosition(int x, int y, int z, BoundingBox playerCollision) {} diff --git a/core/src/main/java/org/geysermc/geyser/translator/collision/SnowCollision.java b/core/src/main/java/org/geysermc/geyser/translator/collision/SnowCollision.java deleted file mode 100644 index af2bcb7ea..000000000 --- a/core/src/main/java/org/geysermc/geyser/translator/collision/SnowCollision.java +++ /dev/null @@ -1,89 +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; -import org.geysermc.geyser.level.physics.BoundingBox; -import org.geysermc.geyser.session.GeyserSession; - -@EqualsAndHashCode(callSuper = true) -//@CollisionRemapper(regex = "^snow$", passDefaultBoxes = true, usesParams = true) TODO remove if no bugs are found. Seems fine with Bedrock 1.20.80 and 1.20.5 -public class SnowCollision extends BlockCollision { - private final int layers; - - public SnowCollision(String params, BoundingBox[] defaultBoxes) { - super(defaultBoxes); - int layerCharIndex = params.indexOf("=") + 1; - layers = Integer.parseInt(params.substring(layerCharIndex, layerCharIndex + 1)); - - pushUpTolerance = 0.125; - } - - // Needs to run before the main correction code or it can move the player into blocks - // This is counteracted by the main collision code pushing them out - @Override - public void beforeCorrectPosition(int x, int y, int z, BoundingBox playerCollision) { - // In Bedrock, snow layers round down to half blocks but you can't sink into them at all - // This means the collision each half block reaches above where it should be on Java so the player has to be - // pushed down - if (layers == 4 || layers == 8) { - double playerMinY = playerCollision.getMiddleY() - (playerCollision.getSizeY() / 2); - double boxMaxY = (boundingBoxes[0].getMiddleY() + y) + (boundingBoxes[0].getSizeY() / 2); - // If the player is in the buggy area, push them down - if (playerMinY > boxMaxY && - playerMinY <= (boxMaxY + 0.125)) { - playerCollision.translate(0, boxMaxY - playerMinY, 0); - } - } - } - - @Override - public boolean correctPosition(GeyserSession session, int x, int y, int z, BoundingBox playerCollision) { - if (layers == 1) { - // 1 layer of snow does not have collision - return true; - } - // Hack to prevent false positives - 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 playerMinY = playerCollision.getMiddleY() - (playerCollision.getSizeY() / 2); - double boxMaxY = (boundingBoxes[0].getMiddleY() + y) + (boundingBoxes[0].getSizeY() / 2); - // If the player actually can't step onto it (they can step onto it from other snow layers) - if ((boxMaxY - playerMinY) > 0.5) { - // Cancel the movement - return false; - } - } - - playerCollision.setSizeX(playerCollision.getSizeX() + 0.0001); - playerCollision.setSizeY(playerCollision.getSizeY() + 0.0001); - playerCollision.setSizeZ(playerCollision.getSizeZ() + 0.0001); - return super.correctPosition(session, x, y, z, playerCollision); - } -} From 9a310f248b265460c14fe944ac42696f056343ff Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Mon, 10 Jun 2024 21:59:03 -0400 Subject: [PATCH 074/233] 1.21-pre4 updated block tags --- .../java/org/geysermc/geyser/session/cache/tags/BlockTag.java | 1 + 1 file changed, 1 insertion(+) 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 index 32d708eca..5a85efc84 100644 --- 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 @@ -42,6 +42,7 @@ public final class BlockTag implements Ordered { public static final BlockTag BUTTONS = new BlockTag("buttons"); public static final BlockTag WOOL_CARPETS = new BlockTag("wool_carpets"); public static final BlockTag WOODEN_DOORS = new BlockTag("wooden_doors"); + public static final BlockTag MOB_INTERACTABLE_DOORS = new BlockTag("mob_interactable_doors"); public static final BlockTag WOODEN_STAIRS = new BlockTag("wooden_stairs"); public static final BlockTag WOODEN_SLABS = new BlockTag("wooden_slabs"); public static final BlockTag WOODEN_FENCES = new BlockTag("wooden_fences"); From d19807170df1b95a8856df4a86e7fc1d7f72b88f Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Mon, 10 Jun 2024 22:40:14 -0400 Subject: [PATCH 075/233] Properly show dyed wolf armor --- .../living/animal/tameable/WolfEntity.java | 2 +- .../java/org/geysermc/geyser/item/Items.java | 4 +- .../geyser/item/type/DyeableArmorItem.java | 7 +-- .../org/geysermc/geyser/item/type/Item.java | 8 ++++ .../geyser/item/type/WolfArmorItem.java | 46 +++++++++++++++++++ .../org/geysermc/geyser/util/ItemUtils.java | 7 ++- 6 files changed, 64 insertions(+), 10 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/item/type/WolfArmorItem.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 9c6c5e08d..e7fde2be8 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 @@ -123,7 +123,7 @@ public class WolfEntity extends TameableEntity { @Override public void setChestplate(ItemStack stack) { super.setChestplate(stack); - isCurseOfBinding = ItemUtils.hasEffect(session, stack.getDataComponents(), EnchantmentComponent.PREVENT_ARMOR_CHANGE); // TODO test + isCurseOfBinding = ItemUtils.hasEffect(session, stack, EnchantmentComponent.PREVENT_ARMOR_CHANGE); // TODO test } @Override 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 82bef33dc..5ae69fa4e 100644 --- a/core/src/main/java/org/geysermc/geyser/item/Items.java +++ b/core/src/main/java/org/geysermc/geyser/item/Items.java @@ -834,7 +834,7 @@ public final class Items { public static final Item TURTLE_HELMET = register(new ArmorItem("turtle_helmet", ArmorMaterial.TURTLE, builder().stackSize(1).maxDamage(275))); 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 WOLF_ARMOR = register(new WolfArmorItem("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 BOWL = register(new Item("bowl", builder())); public static final Item APPLE = register(new Item("apple", builder())); @@ -1042,7 +1042,7 @@ public final class Items { public static final Item BLAZE_POWDER = register(new Item("blaze_powder", builder())); public static final Item MAGMA_CREAM = register(new Item("magma_cream", builder())); public static final Item BREWING_STAND = register(new BlockItem(builder(), Blocks.BREWING_STAND)); - public static final Item CAULDRON = register(new BlockItem(builder(), Blocks.CAULDRON, Blocks.LAVA_CAULDRON, Blocks.WATER_CAULDRON, Blocks.POWDER_SNOW_CAULDRON)); + public static final Item CAULDRON = register(new BlockItem(builder(), Blocks.CAULDRON, Blocks.WATER_CAULDRON, Blocks.LAVA_CAULDRON, Blocks.POWDER_SNOW_CAULDRON)); 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())); 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 b2dbb95e5..8c63eaeb0 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 @@ -29,9 +29,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.item.ArmorMaterial; 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 { public DyeableArmorItem(String javaIdentifier, ArmorMaterial material, Builder builder) { @@ -44,9 +42,6 @@ public class DyeableArmorItem extends ArmorItem { // 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()); - } + translateDyedColor(components, builder); } } 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 8c67d7d5f..2caa65dac 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 @@ -48,6 +48,7 @@ import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.mcprotocollib.protocol.data.game.Identifier; 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; import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemEnchantments; import java.util.ArrayList; @@ -253,6 +254,13 @@ public class Item { builder.getOrCreateLore().add(0, ChatColor.RESET + ChatColor.GRAY + enchantmentName + " " + lvlTranslation); } + protected final void translateDyedColor(DataComponents components, BedrockItemBuilder builder) { + DyedItemColor dyedItemColor = components.get(DataComponentType.DYED_COLOR); + if (dyedItemColor != null) { + builder.putInt("customColor", dyedItemColor.getRgb()); + } + } + /* Translation methods end */ public GeyserItemStack newItemStack(int count, DataComponents components) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/WolfArmorItem.java b/core/src/main/java/org/geysermc/geyser/item/type/WolfArmorItem.java new file mode 100644 index 000000000..bd97a6a7d --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/item/type/WolfArmorItem.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 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.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.item.ArmorMaterial; +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 WolfArmorItem extends ArmorItem { + public WolfArmorItem(String javaIdentifier, ArmorMaterial material, Builder builder) { + super(javaIdentifier, material, builder); + } + + @Override + public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { + super.translateComponentsToBedrock(session, components, builder); + + // Note that this is handled as of 1.21 in the ItemColors class. + translateDyedColor(components, builder); + } +} 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 bbb64a41e..eec0d173d 100644 --- a/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/ItemUtils.java @@ -34,6 +34,7 @@ import org.geysermc.geyser.item.enchantment.EnchantmentComponent; import org.geysermc.geyser.item.type.FishingRodItem; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; +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; @@ -65,7 +66,11 @@ public final class ItemUtils { return 0; } - public static boolean hasEffect(GeyserSession session, @Nullable DataComponents components, EnchantmentComponent component) { + public static boolean hasEffect(GeyserSession session, @Nullable ItemStack itemStack, EnchantmentComponent component) { + if (itemStack == null) { + return false; + } + DataComponents components = itemStack.getDataComponents(); if (components == null) { return false; } From 956a84a3fbbcc04bade20448e3d5009a07ea086e Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 11 Jun 2024 10:47:26 -0400 Subject: [PATCH 076/233] Enchantment tag can be null --- .../java/org/geysermc/geyser/session/cache/TagCache.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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 335e940f4..933b57db7 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 @@ -26,6 +26,7 @@ package org.geysermc.geyser.session.cache; import it.unimi.dsi.fastutil.ints.IntArrays; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.inventory.GeyserItemStack; @@ -83,8 +84,12 @@ public final class TagCache { loadTags("Enchantment", enchantmentTags, ALL_ENCHANTMENT_TAGS, this.enchantments); } - private void loadTags(String type, Map packetTags, Map allTags, int[][] localValues) { + private void loadTags(String type, @Nullable Map packetTags, Map allTags, int[][] localValues) { Arrays.fill(localValues, IntArrays.EMPTY_ARRAY); + if (packetTags == null) { + GeyserImpl.getInstance().getLogger().debug("Not loading " + type + " tags; they do not exist here."); + return; + } allTags.forEach((location, tag) -> { int[] values = packetTags.get(location); if (values != null) { From b78c7b2bd3dd94dc45c91e2a4cabfb4b77cabe7c Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 11 Jun 2024 10:54:57 -0400 Subject: [PATCH 077/233] Fix #4729 --- .../level/block/entity/DoubleChestBlockEntityTranslator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 102f4a0e6..988d94073 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 @@ -38,7 +38,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType * Chests have more block entity properties in Bedrock, which is solved by implementing the BedrockChunkWantsBlockEntityTag */ @BlockEntity(type = { BlockEntityType.CHEST, BlockEntityType.TRAPPED_CHEST }) -public class DoubleChestBlockEntityTranslator extends BlockEntityTranslator { +public class DoubleChestBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { @Override public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) { From 29dacd2397e9e3688141dbf61874daab9776c343 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 11 Jun 2024 14:26:53 -0400 Subject: [PATCH 078/233] Properly remap coral blocks on 1.20.80 --- .../registry/populator/Conversion685_671.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion685_671.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion685_671.java index 250fd9d9f..0b0731707 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion685_671.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion685_671.java @@ -51,16 +51,16 @@ public class Conversion685_671 { if (NEW_CORAL_BLOCKS.contains(identifer)) { switch (identifer) { - case "minecraft:tube_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(0); } - case "minecraft:brain_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(1); } - case "minecraft:bubble_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(2); } - case "minecraft:fire_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(3); } - case "minecraft:horn_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(4); } - case "minecraft:dead_tube_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(8); } - case "minecraft:dead_brain_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(9); } - case "minecraft:dead_bubble_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(10); } - case "minecraft:dead_fire_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(11); } - case "minecraft:dead_horn_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:red_flower").withBedrockData(12); } + case "minecraft:tube_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:coral_block").withBedrockData(0); } + case "minecraft:brain_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:coral_block").withBedrockData(1); } + case "minecraft:bubble_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:coral_block").withBedrockData(2); } + case "minecraft:fire_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:coral_block").withBedrockData(3); } + case "minecraft:horn_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:coral_block").withBedrockData(4); } + case "minecraft:dead_tube_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:coral_block").withBedrockData(8); } + case "minecraft:dead_brain_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:coral_block").withBedrockData(9); } + case "minecraft:dead_bubble_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:coral_block").withBedrockData(10); } + case "minecraft:dead_fire_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:coral_block").withBedrockData(11); } + case "minecraft:dead_horn_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:coral_block").withBedrockData(12); } } } From a42c979abb0a9b20588f60e7b0d6be254021f9f2 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Wed, 12 Jun 2024 00:12:15 -0400 Subject: [PATCH 079/233] This variant of tag loading should be slightly more efficient --- .../java/org/geysermc/geyser/session/cache/TagCache.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 933b57db7..656a16cf4 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 @@ -85,8 +85,8 @@ public final class TagCache { } private void loadTags(String type, @Nullable Map packetTags, Map allTags, int[][] localValues) { - Arrays.fill(localValues, IntArrays.EMPTY_ARRAY); if (packetTags == null) { + Arrays.fill(localValues, IntArrays.EMPTY_ARRAY); GeyserImpl.getInstance().getLogger().debug("Not loading " + type + " tags; they do not exist here."); return; } @@ -95,8 +95,11 @@ public final class TagCache { if (values != null) { if (values.length != 0) { localValues[tag.ordinal()] = values; + } else { + localValues[tag.ordinal()] = IntArrays.EMPTY_ARRAY; } } else { + localValues[tag.ordinal()] = IntArrays.EMPTY_ARRAY; GeyserImpl.getInstance().getLogger().debug(type + " tag not found from server: " + location); } }); From 82d68bfe9bee47dcd90723044d22841c5ca9f60f Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Thu, 13 Jun 2024 00:14:10 +0200 Subject: [PATCH 080/233] Bump fabric/neoforge dependencies to 1.21, update README.md, bump Geyser version to 2.4.0 --- README.md | 2 +- .../src/main/resources/META-INF/neoforge.mods.toml | 2 +- .../main/kotlin/geyser.modded-conventions.gradle.kts | 11 ++++++++--- gradle.properties | 2 +- gradle/libs.versions.toml | 8 ++++---- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index dd2d096ec..c45af73ed 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.80 - 1.21.0 and Minecraft Java 1.20.5/1.20.6 +### Currently supporting Minecraft Bedrock 1.20.80 - 1.21.0 and Minecraft Java 1.21 ## Setting Up Take a look [here](https://wiki.geysermc.org/geyser/setup/) for how to set up Geyser. diff --git a/bootstrap/mod/neoforge/src/main/resources/META-INF/neoforge.mods.toml b/bootstrap/mod/neoforge/src/main/resources/META-INF/neoforge.mods.toml index ff2823aa2..3a25f6119 100644 --- a/bootstrap/mod/neoforge/src/main/resources/META-INF/neoforge.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.5,1.21)" + versionRange="[1.20.5,)" 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 b75e9c5be..6472e4312 100644 --- a/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts @@ -110,18 +110,23 @@ afterEvaluate { } dependencies { - minecraft("com.mojang:minecraft:1.20.5") + minecraft("com.mojang:minecraft:1.21-rc1") mappings(loom.officialMojangMappings()) } repositories { // mavenLocal() - maven("https://repo.opencollab.dev/maven-releases/") - maven("https://repo.opencollab.dev/maven-snapshots/") + maven("https://repo.opencollab.dev/main") 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") + maven("https://prmaven.neoforged.net/NeoForge/pr1076") { + name = "Maven for 1.21 PR" + content { + includeModule("net.neoforged", "neoforge") + } + } } modrinth { diff --git a/gradle.properties b/gradle.properties index ea473906a..a222b1d99 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,5 +7,5 @@ org.gradle.vfs.watch=false group=org.geysermc id=geyser -version=2.3.2-SNAPSHOT +version=2.4.0-SNAPSHOT description=Allows for players from Minecraft: Bedrock Edition to join Minecraft: Java Edition servers. diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index afd001220..11851a5cd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -28,11 +28,11 @@ commodore = "2.2" bungeecord = "a7c6ede" velocity = "3.3.0-SNAPSHOT" viaproxy = "3.2.1" -fabric-minecraft = "1.20.5" -fabric-loader = "0.15.10" -fabric-api = "0.97.6+1.20.5" +fabric-minecraft = "1.21-rc1" +fabric-loader = "0.15.11" +fabric-api = "0.100.1+1.21" fabric-permissions = "0.2-SNAPSHOT" -neoforge-minecraft = "20.5.0-beta" +neoforge-minecraft = "21.0.0-alpha.1.21-rc1.20240611.001314" mixin = "0.8.5" # plugin versions From ecffb564ed568babe1e73af2f7b3c806a2f3f49b Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Wed, 12 Jun 2024 20:34:42 -0400 Subject: [PATCH 081/233] Refactor static recipe loading The only recipes added should be the ones that are sent on Bedrock, so it appears in the recipe book. Every other recipe will be handled through our fallback system. --- .../geyser/inventory/recipe/GeyserRecipe.java | 6 + .../geysermc/geyser/item/type/BannerItem.java | 15 +- .../geyser/item/type/EnchantedBookItem.java | 16 +- .../geyser/item/type/FireworkRocketItem.java | 4 +- .../geyser/item/type/FireworkStarItem.java | 4 +- .../org/geysermc/geyser/item/type/Item.java | 37 +-- .../geysermc/geyser/registry/Registries.java | 13 +- .../registry/loader/RecipeRegistryLoader.java | 149 ++++++++++ .../populator/RecipeRegistryPopulator.java | 233 --------------- .../geyser/session/GeyserSession.java | 3 +- .../inventory/PlayerInventoryTranslator.java | 2 +- .../translator/item/ItemTranslator.java | 13 +- .../java/JavaUpdateRecipesTranslator.java | 270 +++++++++++------- core/src/main/resources/mappings | 2 +- 14 files changed, 360 insertions(+), 407 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/registry/loader/RecipeRegistryLoader.java delete mode 100644 core/src/main/java/org/geysermc/geyser/registry/populator/RecipeRegistryPopulator.java 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 9d98e9fb3..8b7fa9522 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 @@ -25,6 +25,9 @@ package org.geysermc.geyser.inventory.recipe; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; + /** * A more compact version of {@link org.geysermc.mcprotocollib.protocol.data.game.recipe.Recipe}. */ @@ -33,4 +36,7 @@ public interface GeyserRecipe { * Whether the recipe is flexible or not in which items can be placed where. */ boolean isShaped(); + + @Nullable + ItemStack result(); } 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 cf0105622..4af2b4630 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 @@ -60,9 +60,6 @@ public class BannerItem extends BlockItem { */ private static final List> OMINOUS_BANNER_PATTERN; - // 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( @@ -215,20 +212,22 @@ public class BannerItem extends BlockItem { } @Override - public void translateNbtToJava(@NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) { - super.translateNbtToJava(bedrockTag, components, mapping); + public void translateNbtToJava(@NonNull GeyserSession session, @NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) { + super.translateNbtToJava(session, bedrockTag, components, mapping); if (bedrockTag.getInt("Type") == 1) { // Ominous banner pattern List patternLayers = new ArrayList<>(); - for (int i = 0; i < ominousBannerPattern.length; i++) { - patternLayers.add(new BannerPatternLayer(Holder.ofId(ominousBannerPattern[i]), OMINOUS_BANNER_PATTERN.get(i).right().ordinal())); + for (int i = 0; i < OMINOUS_BANNER_PATTERN.size(); i++) { + var pair = OMINOUS_BANNER_PATTERN.get(i); + patternLayers.add(new BannerPatternLayer(Holder.ofId(session.getRegistryCache().bannerPatterns().byValue(pair.left())), + pair.right().ordinal())); } components.put(DataComponentType.BANNER_PATTERNS, patternLayers); components.put(DataComponentType.HIDE_ADDITIONAL_TOOLTIP, Unit.INSTANCE); components.put(DataComponentType.ITEM_NAME, Component - .translatable("block.minecraft.ominous_banner") // thank god this works + .translatable("block.minecraft.ominous_banner") .style(Style.style(TextColor.color(16755200))) ); } 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 540270555..8b0f3e22e 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 @@ -32,6 +32,7 @@ import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtType; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.item.BedrockEnchantment; +import org.geysermc.geyser.item.enchantment.Enchantment; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.item.BedrockItemBuilder; @@ -69,8 +70,8 @@ public class EnchantedBookItem extends Item { } @Override - public void translateNbtToJava(@NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) { - super.translateNbtToJava(bedrockTag, components, mapping); + public void translateNbtToJava(@NonNull GeyserSession session, @NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) { + super.translateNbtToJava(session, bedrockTag, components, mapping); List enchantmentTag = bedrockTag.getList("ench", NbtType.COMPOUND); if (enchantmentTag != null) { @@ -80,9 +81,14 @@ public class EnchantedBookItem extends Item { BedrockEnchantment enchantment = BedrockEnchantment.getByBedrockId(bedrockId); if (enchantment != null) { - int level = bedrockEnchantment.getShort("lvl", (short) 1); - // TODO - //javaEnchantments.put(BedrockEnchantment.JavaEnchantment.valueOf(enchantment.name()).ordinal(), level); + List enchantments = session.getRegistryCache().enchantments().values(); + for (int i = 0; i < enchantments.size(); i++) { + if (enchantments.get(i).bedrockEnchantment() == enchantment) { + int level = bedrockEnchantment.getShort("lvl", (short) 1); + javaEnchantments.put(i, level); + break; + } + } } else { GeyserImpl.getInstance().getLogger().debug("Unknown bedrock enchantment: " + bedrockId); } 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 c70467b4c..9c637afde 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 @@ -70,8 +70,8 @@ public class FireworkRocketItem extends Item { } @Override - public void translateNbtToJava(@NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) { - super.translateNbtToJava(bedrockTag, components, mapping); + public void translateNbtToJava(@NonNull GeyserSession session, @NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) { + super.translateNbtToJava(session, bedrockTag, components, mapping); NbtMap fireworksTag = bedrockTag.getCompound("Fireworks"); if (!fireworksTag.isEmpty()) { 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 18234975d..2ba9b4258 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 @@ -78,8 +78,8 @@ public class FireworkStarItem extends Item { } @Override - public void translateNbtToJava(@NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) { - super.translateNbtToJava(bedrockTag, components, mapping); + public void translateNbtToJava(@NonNull GeyserSession session, @NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) { + super.translateNbtToJava(session, bedrockTag, components, mapping); NbtMap explosion = bedrockTag.getCompound("FireworksItem"); if (!explosion.isEmpty()) { 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 2caa65dac..1ebf85065 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 @@ -172,7 +172,7 @@ public class Item { * * Therefore, if translation cannot be achieved for a certain item, it is not necessarily bad. */ - public void translateNbtToJava(@NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) { + public void translateNbtToJava(@NonNull GeyserSession session, @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) { @@ -190,41 +190,6 @@ public class Item { // } // displayTag.put(new ListTag("Lore", lore)); // } -// } - - // 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; -// -// BedrockEnchantment enchantment = BedrockEnchantment.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); -// } -// } // } } 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 7815768ef..deafbdf7e 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/Registries.java +++ b/core/src/main/java/org/geysermc/geyser/registry/Registries.java @@ -25,14 +25,12 @@ package org.geysermc.geyser.registry; -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.Object2ObjectOpenHashMap; import org.cloudburstmc.nbt.NbtMap; 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; @@ -42,7 +40,7 @@ import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.registry.loader.*; import org.geysermc.geyser.registry.populator.ItemRegistryPopulator; import org.geysermc.geyser.registry.populator.PacketRegistryPopulator; -import org.geysermc.geyser.registry.populator.RecipeRegistryPopulator; +import org.geysermc.geyser.registry.loader.RecipeRegistryLoader; import org.geysermc.geyser.registry.provider.ProviderSupplier; import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.registry.type.ParticleMapping; @@ -95,11 +93,6 @@ public final class Registries { */ public static final SimpleMappedRegistry BLOCK_ENTITIES = SimpleMappedRegistry.create("org.geysermc.geyser.translator.level.block.entity.BlockEntity", BlockEntityRegistryLoader::new); - /** - * A versioned registry which holds a {@link RecipeType} to a corresponding list of {@link RecipeData}. - */ - public static final VersionedRegistry>> CRAFTING_DATA = VersionedRegistry.create(RegistryLoaders.empty(Int2ObjectOpenHashMap::new)); - /** * A map containing all entity types and their respective Geyser definitions */ @@ -147,7 +140,7 @@ public final class Registries { /** * A versioned registry holding all the recipes, with the net ID being the key, and {@link GeyserRecipe} as the value. */ - public static final VersionedRegistry> RECIPES = VersionedRegistry.create(RegistryLoaders.empty(Int2ObjectOpenHashMap::new)); + public static final SimpleMappedRegistry> RECIPES = SimpleMappedRegistry.create("mappings/recipes.nbt", RecipeRegistryLoader::new); /** * A mapped registry holding {@link ResourcePack}'s with the pack uuid as keys. @@ -176,7 +169,7 @@ public final class Registries { static { PacketRegistryPopulator.populate(); ItemRegistryPopulator.populate(); - RecipeRegistryPopulator.populate(); + System.out.println(RECIPES.get()); // Create registries that require other registries to load first POTION_MIXES = VersionedRegistry.create(PotionMixRegistryLoader::new); diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/RecipeRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/RecipeRegistryLoader.java new file mode 100644 index 000000000..5d1236581 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/RecipeRegistryLoader.java @@ -0,0 +1,149 @@ +/* + * 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.loader; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import it.unimi.dsi.fastutil.Pair; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.cloudburstmc.nbt.NBTInputStream; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.nbt.NbtType; +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.text.GeyserLocale; +import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodec; +import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; +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.data.game.recipe.RecipeType; + +import java.io.DataInputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Base64; +import java.util.List; +import java.util.Map; + +/** + * Populates the recipe registry with some recipes that Java does not send, to ensure they show up as intended + * in the recipe book. + */ +public final class RecipeRegistryLoader implements RegistryLoader>> { + + @Override + public Map> load(String input) { + Map> deserializedRecipes = new Object2ObjectOpenHashMap<>(); + + List recipes; + try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow("mappings/recipes.nbt")) { + try (NBTInputStream nbtStream = new NBTInputStream(new DataInputStream(stream))) { + recipes = ((NbtMap) nbtStream.readTag()).getList("recipes", NbtType.COMPOUND); + } + } catch (Exception e) { + throw new AssertionError(GeyserLocale.getLocaleStringLog("geyser.toolbox.fail.runtime_java"), e); + } + + MinecraftCodecHelper helper = MinecraftCodec.CODEC.getHelperFactory().get(); + for (NbtMap recipeCollection : recipes) { + var pair = getRecipes(recipeCollection, helper); + deserializedRecipes.put(pair.key(), pair.value()); + } + return deserializedRecipes; + } + + private static Pair> getRecipes(NbtMap recipes, MinecraftCodecHelper helper) { + List typedRecipes = recipes.getList("recipes", NbtType.COMPOUND); + RecipeType recipeType = RecipeType.from(recipes.getInt("recipe_type", -1)); + if (recipeType == RecipeType.CRAFTING_SPECIAL_TIPPEDARROW) { + return Pair.of(recipeType, getShapedRecipes(typedRecipes, helper)); + } else { + return Pair.of(recipeType, getShapelessRecipes(typedRecipes, helper)); + } + } + + private static List getShapelessRecipes(List recipes, MinecraftCodecHelper helper) { + List deserializedRecipes = new ObjectArrayList<>(recipes.size()); + for (NbtMap recipe : recipes) { + ItemStack output = toItemStack(recipe.getCompound("output"), helper); + List rawInputs = recipe.getList("inputs", NbtType.COMPOUND); + Ingredient[] javaInputs = new Ingredient[rawInputs.size()]; + for (int i = 0; i < rawInputs.size(); i++) { + javaInputs[i] = new Ingredient(new ItemStack[] {toItemStack(rawInputs.get(i), helper)}); + } + deserializedRecipes.add(new GeyserShapelessRecipe(javaInputs, output)); + } + return deserializedRecipes; + } + + private static List getShapedRecipes(List recipes, MinecraftCodecHelper helper) { + List deserializedRecipes = new ObjectArrayList<>(recipes.size()); + for (NbtMap recipe : recipes) { + ItemStack output = toItemStack(recipe.getCompound("output"), helper); + List shape = recipe.getList("shape", NbtType.INT_ARRAY); + + // In the recipes mapping, each recipe is mapped by a number + List letterToRecipe = new ArrayList<>(); + for (NbtMap rawInput : recipe.getList("inputs", NbtType.COMPOUND)) { + letterToRecipe.add(toItemStack(rawInput, helper)); + } + + Ingredient[] inputs = new Ingredient[shape.size() * shape.get(0).length]; + int i = 0; + // Create a linear array of items from the "cube" of the shape + for (int j = 0; i < shape.size() * shape.get(0).length; j++) { + for (int index : shape.get(j)) { + ItemStack stack = letterToRecipe.get(index); + inputs[i++] = new Ingredient(new ItemStack[] {stack}); + } + } + deserializedRecipes.add(new GeyserShapedRecipe(shape.size(), shape.get(0).length, inputs, output)); + } + return deserializedRecipes; + } + + /** + * Converts our serialized NBT into an ItemStack. + * id is the Java item ID as an integer, components is an optional String of the data components serialized + * as bytes in Base64 (so MCProtocolLib can parse the data). + */ + private static ItemStack toItemStack(NbtMap nbt, MinecraftCodecHelper helper) { + int id = nbt.getInt("id"); + int count = nbt.getInt("count"); + String componentsRaw = nbt.getString("components", null); + if (componentsRaw != null) { + byte[] bytes = Base64.getDecoder().decode(componentsRaw); + ByteBuf buf = Unpooled.wrappedBuffer(bytes); + DataComponents components = helper.readDataComponentPatch(buf); + return new ItemStack(id, count, components); + } + return new ItemStack(id, count); + } +} 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 deleted file mode 100644 index 4c6d53518..000000000 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/RecipeRegistryPopulator.java +++ /dev/null @@ -1,233 +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.registry.populator; - -import com.fasterxml.jackson.databind.JsonNode; -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; -import org.cloudburstmc.nbt.NbtMap; -import org.cloudburstmc.nbt.NbtUtils; -import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; -import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.RecipeUnlockingRequirement; -import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.MultiRecipeData; -import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.RecipeData; -import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.ShapedRecipeData; -import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.ShapelessRecipeData; -import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.ItemDescriptorWithCount; -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.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.item.ItemTranslator; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.*; - -import static org.geysermc.geyser.util.InventoryUtils.LAST_RECIPE_NET_ID; - -/** - * Populates the recipe registry. - */ -public class RecipeRegistryPopulator { - - public static void populate() { - JsonNode items; - 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); - } - - int currentRecipeId = LAST_RECIPE_NET_ID; - for (Int2ObjectMap.Entry version : Registries.ITEMS.get().int2ObjectEntrySet()) { - // Make a bit of an assumption here that the last recipe net ID will be equivalent between all versions - LAST_RECIPE_NET_ID = currentRecipeId; - Map> craftingData = new EnumMap<>(RecipeType.class); - Int2ObjectMap recipes = new Int2ObjectOpenHashMap<>(); - - craftingData.put(RecipeType.CRAFTING_SPECIAL_BOOKCLONING, - Collections.singletonList(MultiRecipeData.of(UUID.fromString("d1ca6b84-338e-4f2f-9c6b-76cc8b4bd98d"), ++LAST_RECIPE_NET_ID))); - craftingData.put(RecipeType.CRAFTING_SPECIAL_REPAIRITEM, - Collections.singletonList(MultiRecipeData.of(UUID.fromString("00000000-0000-0000-0000-000000000001"), ++LAST_RECIPE_NET_ID))); - craftingData.put(RecipeType.CRAFTING_SPECIAL_MAPEXTENDING, - Collections.singletonList(MultiRecipeData.of(UUID.fromString("d392b075-4ba1-40ae-8789-af868d56f6ce"), ++LAST_RECIPE_NET_ID))); - craftingData.put(RecipeType.CRAFTING_SPECIAL_MAPCLONING, - Collections.singletonList(MultiRecipeData.of(UUID.fromString("85939755-ba10-4d9d-a4cc-efb7a8e943c4"), ++LAST_RECIPE_NET_ID))); - - // https://github.com/pmmp/PocketMine-MP/blob/stable/src/pocketmine/inventory/MultiRecipe.php - - for (JsonNode entry : items.get("leather_armor")) { - // This won't be perfect, as we can't possibly send every leather input for every kind of color - // But it does display the correct output from a base leather armor, and besides visuals everything works fine - craftingData.computeIfAbsent(RecipeType.CRAFTING_SPECIAL_ARMORDYE, - c -> new ObjectArrayList<>()).add(getCraftingDataFromJsonNode(entry, recipes, version.getValue())); - } - for (JsonNode entry : items.get("firework_rockets")) { - craftingData.computeIfAbsent(RecipeType.CRAFTING_SPECIAL_FIREWORK_ROCKET, - c -> new ObjectArrayList<>()).add(getCraftingDataFromJsonNode(entry, recipes, version.getValue())); - } - for (JsonNode entry : items.get("firework_stars")) { - craftingData.computeIfAbsent(RecipeType.CRAFTING_SPECIAL_FIREWORK_STAR, - c -> new ObjectArrayList<>()).add(getCraftingDataFromJsonNode(entry, recipes, version.getValue())); - } - for (JsonNode entry : items.get("shulker_boxes")) { - craftingData.computeIfAbsent(RecipeType.CRAFTING_SPECIAL_SHULKERBOXCOLORING, - c -> new ObjectArrayList<>()).add(getCraftingDataFromJsonNode(entry, recipes, version.getValue())); - } - for (JsonNode entry : items.get("suspicious_stew")) { - craftingData.computeIfAbsent(RecipeType.CRAFTING_SPECIAL_SUSPICIOUSSTEW, - c -> new ObjectArrayList<>()).add(getCraftingDataFromJsonNode(entry, recipes, version.getValue())); - } - for (JsonNode entry : items.get("tipped_arrows")) { - craftingData.computeIfAbsent(RecipeType.CRAFTING_SPECIAL_TIPPEDARROW, - c -> new ObjectArrayList<>()).add(getCraftingDataFromJsonNode(entry, recipes, version.getValue())); - } - - Registries.CRAFTING_DATA.register(version.getIntKey(), craftingData); - Registries.RECIPES.register(version.getIntKey(), recipes); - } - } - - /** - * Computes a Bedrock crafting recipe from the given JSON data. - * @param node the JSON data to compute - * @param recipes a list of all the recipes - * @return the {@link RecipeData} to send to the Bedrock client. - */ - private static RecipeData getCraftingDataFromJsonNode(JsonNode node, Int2ObjectMap recipes, ItemMappings mappings) { - int netId = ++LAST_RECIPE_NET_ID; - int type = node.get("bedrockRecipeType").asInt(); - JsonNode outputNode = node.get("output"); - ItemMapping outputEntry = mappings.getMapping(outputNode.get("identifier").asText()); - ItemData output = getBedrockItemFromIdentifierJson(outputEntry, outputNode); - UUID uuid = UUID.randomUUID(); - if (type == 1) { - // Shaped recipe - List shape = new ArrayList<>(); - // Get the shape of the recipe - for (JsonNode chars : node.get("shape")) { - shape.add(chars.asText()); - } - - // In recipes.json each recipe is mapped by a letter - Map letterToRecipe = new HashMap<>(); - Iterator> iterator = node.get("inputs").fields(); - while (iterator.hasNext()) { - Map.Entry entry = iterator.next(); - JsonNode inputNode = entry.getValue(); - ItemMapping inputEntry = mappings.getMapping(inputNode.get("identifier").asText()); - letterToRecipe.put(entry.getKey(), getBedrockItemFromIdentifierJson(inputEntry, inputNode)); - } - - List inputs = new ArrayList<>(shape.size() * shape.get(0).length()); - int i = 0; - // Create a linear array of items from the "cube" of the shape - for (int j = 0; i < shape.size() * shape.get(0).length(); j++) { - for (char c : shape.get(j).toCharArray()) { - ItemData data = letterToRecipe.getOrDefault(String.valueOf(c), ItemData.AIR); - inputs.add(data); - i++; - } - } - - /* Convert into a Java recipe class for autocrafting */ - List ingredients = new ArrayList<>(); - for (ItemData input : inputs) { - ingredients.add(new Ingredient(new ItemStack[]{ItemTranslator.translateToJava(input, mappings)})); - } - GeyserRecipe recipe = new GeyserShapedRecipe(shape.get(0).length(), shape.size(), - ingredients.toArray(new Ingredient[0]), ItemTranslator.translateToJava(output, mappings)); - recipes.put(netId, recipe); - /* 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, false, RecipeUnlockingRequirement.INVALID); - } - List inputs = new ObjectArrayList<>(); - for (JsonNode entry : node.get("inputs")) { - ItemMapping inputEntry = mappings.getMapping(entry.get("identifier").asText()); - inputs.add(getBedrockItemFromIdentifierJson(inputEntry, entry)); - } - - /* Convert into a Java Recipe class for autocrafting */ - List ingredients = new ArrayList<>(); - for (ItemData input : inputs) { - ingredients.add(new Ingredient(new ItemStack[]{ItemTranslator.translateToJava(input, mappings)})); - } - GeyserRecipe recipe = new GeyserShapelessRecipe(ingredients.toArray(new Ingredient[0]), ItemTranslator.translateToJava(output, mappings)); - recipes.put(netId, recipe); - /* Convert end */ - - if (type == 5) { - // Shulker box - return ShapelessRecipeData.shulkerBox(uuid.toString(), - inputs.stream().map(ItemDescriptorWithCount::fromItem).toList(), Collections.singletonList(output), uuid, "crafting_table", 0, netId); - } - return ShapelessRecipeData.shapeless(uuid.toString(), - inputs.stream().map(ItemDescriptorWithCount::fromItem).toList(), Collections.singletonList(output), uuid, "crafting_table", 0, netId, RecipeUnlockingRequirement.INVALID); - } - - private static ItemData getBedrockItemFromIdentifierJson(ItemMapping mapping, JsonNode itemNode) { - int count = 1; - short damage = 0; - NbtMap tag = null; - JsonNode damageNode = itemNode.get("bedrockDamage"); - if (damageNode != null) { - damage = damageNode.numberValue().shortValue(); - } - JsonNode countNode = itemNode.get("count"); - if (countNode != null) { - count = countNode.asInt(); - } - JsonNode nbtNode = itemNode.get("bedrockNbt"); - if (nbtNode != null) { - byte[] bytes = Base64.getDecoder().decode(nbtNode.asText()); - ByteArrayInputStream bais = new ByteArrayInputStream(bytes); - try { - tag = (NbtMap) NbtUtils.createReaderLE(bais).readTag(); - } catch (IOException e) { - e.printStackTrace(); - } - } - return ItemData.builder() - .definition(mapping.getBedrockDefinition()) - .damage(damage) - .count(count) - .blockDefinition(mapping.getBedrockBlockDefinition()) - .tag(tag) - .build(); - } -} 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 ae5e1d338..836c77379 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -356,8 +356,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { * 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; + private final Map> javaToBedrockRecipeIds; @Setter private Int2ObjectMap craftingRecipes; 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 18d6a22eb..bc6ff2adf 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 @@ -423,7 +423,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { } // Reference the creative items list we send to the client to know what it's asking of us ItemData creativeItem = creativeItems[creativeId]; - javaCreativeItem = ItemTranslator.translateToJava(creativeItem, session.getItemMappings()); + javaCreativeItem = ItemTranslator.translateToJava(session, creativeItem); break; } case CRAFT_RESULTS_DEPRECATED: { 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 251aacba8..8b61e435a 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 @@ -47,7 +47,6 @@ 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.text.ChatColor; import org.geysermc.geyser.text.MinecraftLocale; @@ -83,25 +82,21 @@ public final class ItemTranslator { private ItemTranslator() { } - /** - * @param mappings item mappings to use while translating. This can't just be a Geyser session as this method is used - * when loading recipes. - */ - public static ItemStack translateToJava(ItemData data, ItemMappings mappings) { + public static ItemStack translateToJava(GeyserSession session, ItemData data) { if (data == null) { return new ItemStack(Items.AIR_ID); } - ItemMapping bedrockItem = mappings.getMapping(data); + ItemMapping bedrockItem = session.getItemMappings().getMapping(data); Item javaItem = bedrockItem.getJavaItem(); - GeyserItemStack itemStack = javaItem.translateToJava(data, bedrockItem, mappings); + GeyserItemStack itemStack = javaItem.translateToJava(data, bedrockItem, session.getItemMappings()); NbtMap nbt = data.getTag(); if (nbt != null && !nbt.isEmpty()) { // translateToJava may have added components DataComponents components = itemStack.getComponents() == null ? new DataComponents(new HashMap<>()) : itemStack.getComponents(); - javaItem.translateNbtToJava(nbt, components, bedrockItem); + javaItem.translateNbtToJava(session, nbt, components, bedrockItem); if (!components.getDataComponents().isEmpty()) { itemStack.setComponents(components); } 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 2a0c38221..886b31e09 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 @@ -103,66 +103,31 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator> 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())); + recipeIDs.clear(); + Int2ObjectMap recipeMap = new Int2ObjectOpenHashMap<>(); Int2ObjectMap> unsortedStonecutterData = new Int2ObjectOpenHashMap<>(); CraftingDataPacket craftingDataPacket = new CraftingDataPacket(); craftingDataPacket.setCleanRecipes(true); + RecipeContext context = new RecipeContext(session, craftingDataPacket, recipeMap); + for (Recipe recipe : packet.getRecipes()) { switch (recipe.getType()) { case CRAFTING_SHAPELESS -> { ShapelessRecipeData shapelessRecipeData = (ShapelessRecipeData) recipe.getData(); - ItemData output = ItemTranslator.translateToBedrock(session, shapelessRecipeData.getResult()); - if (!output.isValid()) { - // Likely modded item that Bedrock will complain about if it persists - continue; + List bedrockRecipeIDs = context.translateShapelessRecipe(new GeyserShapelessRecipe(shapelessRecipeData)); + if (bedrockRecipeIDs != null) { + context.addRecipeIdentifier(session, recipe.getIdentifier(), bedrockRecipeIDs); } - // Strip NBT - tools won't appear in the recipe book otherwise - output = output.toBuilder().tag(null).build(); - ItemDescriptorWithCount[][] inputCombinations = combinations(session, shapelessRecipeData.getIngredients()); - if (inputCombinations == null) { - continue; - } - - List 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, RecipeUnlockingRequirement.INVALID)); - recipeMap.put(netId++, new GeyserShapelessRecipe(shapelessRecipeData)); - } - addRecipeIdentifier(session, recipe.getIdentifier(), bedrockRecipeIDs); } case CRAFTING_SHAPED -> { ShapedRecipeData shapedRecipeData = (ShapedRecipeData) recipe.getData(); - ItemData output = ItemTranslator.translateToBedrock(session, shapedRecipeData.getResult()); - if (!output.isValid()) { - // Likely modded item that Bedrock will complain about if it persists - continue; + List bedrockRecipeIDs = context.translateShapedRecipe(new GeyserShapedRecipe(shapedRecipeData)); + if (bedrockRecipeIDs != null) { + context.addRecipeIdentifier(session, recipe.getIdentifier(), bedrockRecipeIDs); } - // See above - output = output.toBuilder().tag(null).build(); - ItemDescriptorWithCount[][] inputCombinations = combinations(session, shapedRecipeData.getIngredients()); - if (inputCombinations == null) { - continue; - } - - List 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, false, RecipeUnlockingRequirement.INVALID)); - recipeMap.put(netId++, new GeyserShapedRecipe(shapedRecipeData)); - } - addRecipeIdentifier(session, recipe.getIdentifier(), bedrockRecipeIDs); } case STONECUTTING -> { StoneCuttingRecipeData stoneCuttingData = (StoneCuttingRecipeData) recipe.getData(); @@ -198,7 +163,7 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator(Collections.singletonList(id))); } @@ -212,13 +177,48 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator { // 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++)); + craftingDataPacket.getCraftingData().add(MultiRecipeData.of(UUID.fromString("685a742a-c42e-4a4e-88ea-5eb83fc98e5b"), context.getAndIncrementNetId())); + } + case CRAFTING_SPECIAL_BOOKCLONING -> { + craftingDataPacket.getCraftingData().add(MultiRecipeData.of(UUID.fromString("d1ca6b84-338e-4f2f-9c6b-76cc8b4bd98d"), context.getAndIncrementNetId())); + } + case CRAFTING_SPECIAL_REPAIRITEM -> { + craftingDataPacket.getCraftingData().add(MultiRecipeData.of(UUID.fromString("00000000-0000-0000-0000-000000000001"), context.getAndIncrementNetId())); + } + case CRAFTING_SPECIAL_MAPEXTENDING -> { + craftingDataPacket.getCraftingData().add(MultiRecipeData.of(UUID.fromString("d392b075-4ba1-40ae-8789-af868d56f6ce"), context.getAndIncrementNetId())); + } + case CRAFTING_SPECIAL_MAPCLONING -> { + craftingDataPacket.getCraftingData().add(MultiRecipeData.of(UUID.fromString("85939755-ba10-4d9d-a4cc-efb7a8e943c4"), context.getAndIncrementNetId())); } default -> { - List craftingData = recipeTypes.get(recipe.getType()); - if (craftingData != null) { - addSpecialRecipesIdentifiers(session, recipe, craftingData); - craftingDataPacket.getCraftingData().addAll(craftingData); + List recipes = Registries.RECIPES.get(recipe.getType()); + if (recipes != null) { + List bedrockRecipeIds = new ArrayList<>(); + if (recipe.getType() == RecipeType.CRAFTING_SPECIAL_TIPPEDARROW) { + // Only shaped recipe at this moment + for (GeyserRecipe builtInRecipe : recipes) { + var recipeIds = context.translateShapedRecipe((GeyserShapedRecipe) builtInRecipe); + if (recipeIds != null) { + bedrockRecipeIds.addAll(recipeIds); + } + } + } else if (recipe.getType() == RecipeType.CRAFTING_SPECIAL_SHULKERBOXCOLORING) { + for (GeyserRecipe builtInRecipe : recipes) { + var recipeIds = context.translateShulkerBoxRecipe((GeyserShapelessRecipe) builtInRecipe); + if (recipeIds != null) { + bedrockRecipeIds.addAll(recipeIds); + } + } + } else { + for (GeyserRecipe builtInRecipe : recipes) { + var recipeIds = context.translateShapelessRecipe((GeyserShapelessRecipe) builtInRecipe); + if (recipeIds != null) { + bedrockRecipeIds.addAll(recipeIds); + } + } + } + context.addSpecialRecipesIdentifiers(recipe, bedrockRecipeIds); } } } @@ -250,17 +250,17 @@ 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); + System.out.println(craftingDataPacket); } //TODO: rewrite @@ -323,7 +292,7 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator, IntSet> squashedOptions = new HashMap<>(); for (int i = 0; i < ingredients.length; i++) { @@ -407,17 +376,6 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator bedrockIdentifiers) { - session.getJavaToBedrockRecipeIds().computeIfAbsent(javaIdentifier, k -> new ArrayList<>()).addAll(bedrockIdentifiers); - } - - @EqualsAndHashCode - @AllArgsConstructor - private static class GroupedItem { - ItemDefinition id; - int count; - } - private List getSmithingTransformRecipes(GeyserSession session) { List recipes = new ArrayList<>(); ItemMapping template = session.getItemMappings().getStoredItems().upgradeTemplate(); @@ -442,4 +400,120 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator recipeMap; + // Get the last known network ID (first used for some pregenerated recipes) and increment from there. + private int netId = InventoryUtils.LAST_RECIPE_NET_ID + 1; + + private RecipeContext(GeyserSession session, CraftingDataPacket packet, Int2ObjectMap recipeMap) { + this.session = session; + this.packet = packet; + this.recipeMap = recipeMap; + } + + List translateShulkerBoxRecipe(GeyserShapelessRecipe recipe) { + ItemData output = ItemTranslator.translateToBedrock(session, recipe.result()); + if (!output.isValid()) { + // Likely modded item that Bedrock will complain about if it persists + return null; + } + // Strip NBT - tools won't appear in the recipe book otherwise + output = output.toBuilder().tag(null).build(); + ItemDescriptorWithCount[][] inputCombinations = combinations(session, recipe.ingredients()); + if (inputCombinations == null) { + return null; + } + + List bedrockRecipeIDs = new ArrayList<>(); + for (ItemDescriptorWithCount[] inputs : inputCombinations) { + UUID uuid = UUID.randomUUID(); + bedrockRecipeIDs.add(uuid.toString()); + packet.getCraftingData().add(org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.ShapelessRecipeData.shulkerBox(uuid.toString(), + Arrays.asList(inputs), Collections.singletonList(output), uuid, "crafting_table", 0, netId)); + recipeMap.put(netId++, recipe); + } + return bedrockRecipeIDs; + } + + List translateShapelessRecipe(GeyserShapelessRecipe recipe) { + ItemData output = ItemTranslator.translateToBedrock(session, recipe.result()); + if (!output.isValid()) { + // Likely modded item that Bedrock will complain about if it persists + return null; + } + // Strip NBT - tools won't appear in the recipe book otherwise + output = output.toBuilder().tag(null).build(); + ItemDescriptorWithCount[][] inputCombinations = combinations(session, recipe.ingredients()); + if (inputCombinations == null) { + return null; + } + + List bedrockRecipeIDs = new ArrayList<>(); + for (ItemDescriptorWithCount[] inputs : inputCombinations) { + UUID uuid = UUID.randomUUID(); + bedrockRecipeIDs.add(uuid.toString()); + packet.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, RecipeUnlockingRequirement.INVALID)); + recipeMap.put(netId++, recipe); + } + return bedrockRecipeIDs; + } + + List translateShapedRecipe(GeyserShapedRecipe recipe) { + ItemData output = ItemTranslator.translateToBedrock(session, recipe.result()); + if (!output.isValid()) { + // Likely modded item that Bedrock will complain about if it persists + return null; + } + // See above + output = output.toBuilder().tag(null).build(); + ItemDescriptorWithCount[][] inputCombinations = combinations(session, recipe.ingredients()); + if (inputCombinations == null) { + return null; + } + + List bedrockRecipeIDs = new ArrayList<>(); + for (ItemDescriptorWithCount[] inputs : inputCombinations) { + UUID uuid = UUID.randomUUID(); + bedrockRecipeIDs.add(uuid.toString()); + packet.getCraftingData().add(org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.ShapedRecipeData.shaped(uuid.toString(), + recipe.width(), recipe.height(), Arrays.asList(inputs), + Collections.singletonList(output), uuid, "crafting_table", 0, netId, false, RecipeUnlockingRequirement.INVALID)); + recipeMap.put(netId++, recipe); + } + return bedrockRecipeIDs; + } + + void addSpecialRecipesIdentifiers(Recipe recipe, List identifiers) { + String javaRecipeID = switch (recipe.getType()) { + case CRAFTING_SPECIAL_SHULKERBOXCOLORING -> + // BDS (un)locks the dyeing with the shulker box recipe, Java never - we want BDS behavior for ease of use + "minecraft:shulker_box"; + case CRAFTING_SPECIAL_TIPPEDARROW -> + // similar as above + "minecraft:arrow"; + default -> recipe.getIdentifier(); + }; + + addRecipeIdentifier(session, javaRecipeID, identifiers); + } + + void addRecipeIdentifier(GeyserSession session, String javaIdentifier, List bedrockIdentifiers) { + session.getJavaToBedrockRecipeIds().computeIfAbsent(javaIdentifier, k -> new ArrayList<>()).addAll(bedrockIdentifiers); + } + + int getAndIncrementNetId() { + return this.netId++; + } + } } diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings index 54705bcd2..8795baeb1 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 54705bcd2bcba830267efbb1fbfd4e52972c40f7 +Subproject commit 8795baeb170f7c9832da2def8625f0c5702abd91 From 2ecc4cd841e9902cb0b2ff3128b4d6592b41fb30 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Wed, 12 Jun 2024 20:42:29 -0400 Subject: [PATCH 082/233] Point to right 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 8795baeb1..396ea5ff5 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 8795baeb170f7c9832da2def8625f0c5702abd91 +Subproject commit 396ea5ff50d8c976fde4e7423e682d21aa0ee350 From 82d0a87020aa9e5621f4d78fbda5a9bb4b0863a0 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Wed, 12 Jun 2024 20:45:47 -0400 Subject: [PATCH 083/233] Remove debug code --- core/src/main/java/org/geysermc/geyser/registry/Registries.java | 1 - .../translator/protocol/java/JavaUpdateRecipesTranslator.java | 1 - 2 files changed, 2 deletions(-) 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 deafbdf7e..30d3c0763 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/Registries.java +++ b/core/src/main/java/org/geysermc/geyser/registry/Registries.java @@ -169,7 +169,6 @@ public final class Registries { static { PacketRegistryPopulator.populate(); ItemRegistryPopulator.populate(); - System.out.println(RECIPES.get()); // Create registries that require other registries to load first POTION_MIXES = VersionedRegistry.create(PotionMixRegistryLoader::new); 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 886b31e09..4d207153b 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 @@ -282,7 +282,6 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator Date: Wed, 12 Jun 2024 20:56:06 -0400 Subject: [PATCH 084/233] Fix some water plants not being waterlogged --- .../geyser/registry/populator/BlockRegistryPopulator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 a8fb0001d..272522429 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 @@ -290,7 +290,8 @@ public final class BlockRegistryPopulator { } boolean waterlogged = blockState.getValue(Properties.WATERLOGGED, false) - || block == Blocks.BUBBLE_COLUMN || block == Blocks.KELP || block == Blocks.SEAGRASS; + || block == Blocks.BUBBLE_COLUMN || block == Blocks.KELP || block == Blocks.KELP_PLANT + || block == Blocks.SEAGRASS || block == Blocks.TALL_SEAGRASS; if (waterlogged) { BlockRegistries.WATERLOGGED.get().set(javaRuntimeId); From 52a93ecc187cd1fdc2bcc0ab66d6c86734ccbbaa Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Wed, 12 Jun 2024 22:16:14 -0400 Subject: [PATCH 085/233] Implement breeze --- .../java/org/geysermc/geyser/entity/EntityDefinitions.java | 5 +++++ .../geyser/entity/type/living/monster/BreezeEntity.java | 4 ++++ 2 files changed, 9 insertions(+) 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 a7c2d6ca6..1496f8a82 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -66,6 +66,7 @@ public final class EntityDefinitions { public static final EntityDefinition BLAZE; public static final EntityDefinition BOAT; public static final EntityDefinition BOGGED; + public static final EntityDefinition BREEZE; public static final EntityDefinition BREEZE_WIND_CHARGE; public static final EntityDefinition CAMEL; public static final EntityDefinition CAT; @@ -530,6 +531,10 @@ public final class EntityDefinitions { .height(1.8f).width(0.6f) .addTranslator(MetadataType.BYTE, BlazeEntity::setBlazeFlags) .build(); + BREEZE = EntityDefinition.inherited(BreezeEntity::new, mobEntityBase) + .type(EntityType.BREEZE) + .height(1.77f).width(0.6f) + .build(); CREEPER = EntityDefinition.inherited(CreeperEntity::new, mobEntityBase) .type(EntityType.CREEPER) .height(1.7f).width(0.6f) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BreezeEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BreezeEntity.java index 25d466aaf..251a77fb9 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BreezeEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/BreezeEntity.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.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; @@ -39,6 +40,9 @@ public class BreezeEntity extends MonsterEntity { @Override public void setPose(Pose pose) { + // TODO Test + setFlag(EntityFlag.FACING_TARGET_TO_RANGE_ATTACK, pose == Pose.SHOOTING); + setFlag(EntityFlag.JUMP_GOAL_JUMP, pose == Pose.INHALING); super.setPose(pose); } } From 3528b1d692b8c19cf8bca187dbc086647f5399ed Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Wed, 12 Jun 2024 22:47:47 -0400 Subject: [PATCH 086/233] Allow recipes to default count as 1 --- .../geysermc/geyser/registry/loader/RecipeRegistryLoader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/RecipeRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/RecipeRegistryLoader.java index 5d1236581..f1d0c456f 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/RecipeRegistryLoader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/RecipeRegistryLoader.java @@ -136,7 +136,7 @@ public final class RecipeRegistryLoader implements RegistryLoader Date: Wed, 12 Jun 2024 23:48:40 -0400 Subject: [PATCH 087/233] Update to latest MCProtocolLib --- .../type/player/SessionPlayerEntity.java | 2 +- .../geyser/inventory/item/BannerPattern.java | 10 +++-- .../geyser/inventory/recipe/TrimRecipe.java | 17 +------- .../geyser/item/enchantment/Enchantment.java | 7 ++-- .../geysermc/geyser/item/type/BannerItem.java | 7 ++-- .../org/geysermc/geyser/item/type/Item.java | 4 +- .../geysermc/geyser/level/PaintingType.java | 8 +++- .../mappings/versions/MappingsReader_v1.java | 20 ++-------- .../geyser/session/GeyserSession.java | 3 +- .../geyser/session/cache/LodestoneCache.java | 9 +++-- .../geyser/session/cache/RegistryCache.java | 16 ++++---- .../geyser/session/cache/TagCache.java | 14 ++++--- .../geyser/session/cache/tags/BlockTag.java | 5 ++- .../session/cache/tags/EnchantmentTag.java | 6 ++- .../geyser/session/cache/tags/ItemTag.java | 6 ++- .../translator/level/BiomeTranslator.java | 2 +- .../BedrockBlockEntityDataTranslator.java | 4 +- ...tionTrackingDBClientRequestTranslator.java | 2 +- .../JavaClientboundRecipesTranslator.java | 1 + .../protocol/java/JavaCommandsTranslator.java | 15 +++---- .../java/JavaCustomPayloadTranslator.java | 4 +- .../java/JavaGameProfileTranslator.java | 3 +- .../protocol/java/JavaLoginTranslator.java | 10 +++-- .../java/JavaUpdateRecipesTranslator.java | 8 ++-- .../player/JavaStoreCookieTranslator.java | 2 +- .../java/level/JavaStopSoundTranslator.java | 2 +- .../geysermc/geyser/util/MinecraftKey.java | 39 +++++++++++++++++++ .../geyser/util/PluginMessageUtils.java | 3 +- gradle/libs.versions.toml | 2 +- 29 files changed, 135 insertions(+), 96 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/util/MinecraftKey.java 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 ad6729c42..31eb02984 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 @@ -220,7 +220,7 @@ public class SessionPlayerEntity extends PlayerEntity { public void setLastDeathPosition(@Nullable GlobalPos pos) { if (pos != null) { dirtyMetadata.put(EntityDataTypes.PLAYER_LAST_DEATH_POS, pos.getPosition()); - dirtyMetadata.put(EntityDataTypes.PLAYER_LAST_DEATH_DIMENSION, DimensionUtils.javaToBedrock(pos.getDimension())); + dirtyMetadata.put(EntityDataTypes.PLAYER_LAST_DEATH_DIMENSION, DimensionUtils.javaToBedrock(pos.getDimension().asString())); dirtyMetadata.put(EntityDataTypes.PLAYER_HAS_DIED, true); } else { dirtyMetadata.put(EntityDataTypes.PLAYER_HAS_DIED, false); 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 b6cc2c206..743fbdc7e 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 @@ -26,7 +26,9 @@ package org.geysermc.geyser.inventory.item; import lombok.Getter; +import net.kyori.adventure.key.Key; import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.util.MinecraftKey; import java.util.Locale; @@ -78,17 +80,17 @@ public enum BannerPattern { private static final BannerPattern[] VALUES = values(); - private final String javaIdentifier; + private final Key javaIdentifier; private final String bedrockIdentifier; BannerPattern(String bedrockIdentifier) { - this.javaIdentifier = "minecraft:" + this.name().toLowerCase(Locale.ROOT); + this.javaIdentifier = MinecraftKey.key(this.name().toLowerCase(Locale.ROOT)); this.bedrockIdentifier = bedrockIdentifier; } - public static @Nullable BannerPattern getByJavaIdentifier(String javaIdentifier) { + public static @Nullable BannerPattern getByJavaIdentifier(Key key) { for (BannerPattern bannerPattern : VALUES) { - if (bannerPattern.javaIdentifier.equals(javaIdentifier)) { + if (bannerPattern.javaIdentifier.equals(key)) { return bannerPattern; } } 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 9d9dbe0db..8289813a4 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 = stripMinecraftNamespace(entry.getId()); + String key = entry.getId().asMinimalString(); // 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 = stripMinecraftNamespace(entry.getId()); + String key = entry.getId().asMinimalString(); String itemIdentifier = entry.getData().getString("template_item"); ItemMapping itemMapping = session.getItemMappings().getMapping(itemIdentifier); @@ -78,19 +78,6 @@ public final class TrimRecipe { return new TrimPattern(itemMapping.getBedrockIdentifier(), key); } - // TODO find a good place for a stripNamespace util method - private static String stripMinecraftNamespace(String identifier) { - int i = identifier.indexOf(':'); - if (i >= 0) { - String namespace = identifier.substring(0, i); - // Only strip minecraft namespace - if (namespace.equals("minecraft")) { - return identifier.substring(i + 1); - } - } - return identifier; - } - private TrimRecipe() { //no-op } diff --git a/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java b/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java index 468b88e87..c5c0d2611 100644 --- a/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java +++ b/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java @@ -31,6 +31,7 @@ import org.geysermc.geyser.inventory.item.BedrockEnchantment; import org.geysermc.geyser.session.cache.tags.EnchantmentTag; import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.translator.text.MessageTranslator; +import org.geysermc.geyser.util.MinecraftKey; import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; import java.util.HashSet; @@ -59,11 +60,11 @@ public record Enchantment(String identifier, int maxLevel = data.getInt("max_level"); int anvilCost = data.getInt("anvil_cost"); String exclusiveSet = data.getString("exclusive_set", null); - EnchantmentTag exclusiveSetTag = exclusiveSet == null ? null : EnchantmentTag.ALL_ENCHANTMENT_TAGS.get(exclusiveSet.substring(1)); - BedrockEnchantment bedrockEnchantment = BedrockEnchantment.getByJavaIdentifier(entry.getId()); + EnchantmentTag exclusiveSetTag = exclusiveSet == null ? null : EnchantmentTag.ALL_ENCHANTMENT_TAGS.get(MinecraftKey.key(exclusiveSet.substring(1))); + BedrockEnchantment bedrockEnchantment = BedrockEnchantment.getByJavaIdentifier(entry.getId().asString()); String description = bedrockEnchantment == null ? MessageTranslator.deserializeDescription(data) : null; - return new Enchantment(entry.getId(), effects, ItemTag.ALL_ITEM_TAGS.get(supportedItems), maxLevel, + return new Enchantment(entry.getId().asString(), effects, ItemTag.ALL_ITEM_TAGS.get(MinecraftKey.key(supportedItems)), maxLevel, description, anvilCost, exclusiveSetTag, bedrockEnchantment); } 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 4af2b4630..6ec0da8ed 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,6 +26,7 @@ package org.geysermc.geyser.item.type; import it.unimi.dsi.fastutil.Pair; +import net.kyori.adventure.key.Key; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.Style; import net.kyori.adventure.text.format.TextColor; @@ -40,8 +41,8 @@ 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.geyser.util.MinecraftKey; 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; @@ -106,7 +107,7 @@ public class BannerItem extends BlockItem { if (color != pair.right()) { return false; } - String id = Identifier.formalize(patternLayer.getString("pattern")); // Ouch + Key id = MinecraftKey.key(patternLayer.getString("pattern")); // Ouch BannerPattern bannerPattern = BannerPattern.getByJavaIdentifier(id); if (bannerPattern != pair.left()) { return false; @@ -166,7 +167,7 @@ public class BannerItem extends BlockItem { */ private static NbtMap getBedrockBannerPattern(NbtMap pattern) { // ViaVersion 1.20.4 -> 1.20.5 can send without the namespace - BannerPattern bannerPattern = BannerPattern.getByJavaIdentifier(Identifier.formalize(pattern.getString("pattern"))); + BannerPattern bannerPattern = BannerPattern.getByJavaIdentifier(MinecraftKey.key(pattern.getString("pattern"))); DyeColor dyeColor = DyeColor.getByJavaIdentifier(pattern.getString("color")); if (bannerPattern == null || dyeColor == null) { return null; 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 1ebf85065..3014e8116 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 @@ -45,7 +45,7 @@ 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.geyser.util.MinecraftKey; 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; @@ -65,7 +65,7 @@ public class Item { private final int maxDamage; public Item(String javaIdentifier, Builder builder) { - this.javaIdentifier = Identifier.formalize(javaIdentifier).intern(); + this.javaIdentifier = MinecraftKey.key(javaIdentifier).asString().intern(); this.stackSize = builder.stackSize; this.maxDamage = builder.maxDamage; this.attackDamage = builder.attackDamage; 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 de35d97f1..f829b481c 100644 --- a/core/src/main/java/org/geysermc/geyser/level/PaintingType.java +++ b/core/src/main/java/org/geysermc/geyser/level/PaintingType.java @@ -28,6 +28,7 @@ package org.geysermc.geyser.level; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; +import net.kyori.adventure.key.Key; import java.util.Locale; @@ -90,9 +91,12 @@ public enum PaintingType { private final int width; private final int height; - public static PaintingType getByName(String javaName) { + public static PaintingType getByName(Key key) { + if (!key.namespace().equals("minecraft")) { + return null; + } for (PaintingType paintingName : VALUES) { - if (("minecraft:" + paintingName.name().toLowerCase(Locale.ROOT)).equals(javaName)) return paintingName; + if (paintingName.name().toLowerCase(Locale.ROOT).equals(key.value())) return paintingName; } 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 d32d5bc09..b5e25a4ba 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,6 @@ package org.geysermc.geyser.registry.mappings.versions; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; -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; @@ -35,14 +34,9 @@ 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.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.*; 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; @@ -60,16 +54,10 @@ 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 org.geysermc.geyser.util.MinecraftKey; import java.nio.file.Path; -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.*; import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.Predicate; @@ -131,7 +119,7 @@ public class MappingsReader_v1 extends MappingsReader { blocksNode.fields().forEachRemaining(entry -> { if (entry.getValue().isObject()) { try { - String identifier = Identifier.formalize(entry.getKey()); + String identifier = MinecraftKey.key(entry.getKey()).asString(); CustomBlockMapping customBlockMapping = this.readBlockMappingEntry(identifier, entry.getValue()); consumer.accept(identifier, customBlockMapping); } catch (Exception e) { 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 836c77379..e228fc02f 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -40,6 +40,7 @@ import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; +import net.kyori.adventure.key.Key; import org.checkerframework.checker.index.qual.NonNegative; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.NonNull; @@ -290,7 +291,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { * Keeps track of the world name for respawning. */ @Setter - private String worldName = null; + private Key worldName = null; /** * As of Java 1.19.3, the client only uses these for commands. */ 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 f66daf027..ee8ebb13f 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 @@ -27,6 +27,7 @@ package org.geysermc.geyser.session.cache; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import net.kyori.adventure.key.Key; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.GlobalPos; @@ -64,7 +65,7 @@ public final class LodestoneCache { int x = position.getX(); int y = position.getY(); int z = position.getZ(); - String dim = position.getDimension(); + Key dim = position.getDimension(); for (LodestonePos pos : this.activeLodestones.values()) { if (pos.equals(x, y, z, dim)) { @@ -98,7 +99,7 @@ public final class LodestoneCache { int x = position.getX(); int y = position.getY(); int z = position.getZ(); - String dim = position.getDimension(); + Key dim = position.getDimension(); for (LodestonePos pos : this.activeLodestones.values()) { if (pos.equals(x, y, z, dim)) { @@ -138,8 +139,8 @@ public final class LodestoneCache { this.lodestones.clear(); } - public record LodestonePos(int id, int x, int y, int z, String dimension) { - boolean equals(int x, int y, int z, String dimension) { + public record LodestonePos(int id, int x, int y, int z, Key dimension) { + boolean equals(int x, int y, int z, Key dimension) { return this.x == x && this.y == y && this.z == z && this.dimension.equals(dimension); } } 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 266a0a418..02c43939d 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 @@ -30,6 +30,7 @@ import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; import lombok.AccessLevel; import lombok.Getter; import lombok.experimental.Accessors; +import net.kyori.adventure.key.Key; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.data.TrimMaterial; @@ -47,6 +48,7 @@ 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.geyser.util.MinecraftKey; import org.geysermc.mcprotocollib.protocol.MinecraftProtocol; import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; import org.geysermc.mcprotocollib.protocol.data.game.chat.ChatType; @@ -70,8 +72,8 @@ import java.util.function.ToIntFunction; @Accessors(fluent = true) @Getter public final class RegistryCache { - private static final Map> DEFAULTS; - private static final Map>> REGISTRIES = new HashMap<>(); + private static final Map> DEFAULTS; + private static final Map>> REGISTRIES = new HashMap<>(); static { register("chat_type", cache -> cache.chatTypes, ($, entry) -> TextDecoration.readChatType(entry)); @@ -83,14 +85,14 @@ 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.BuiltInWolfVariant.getByJavaIdentifier(entry.getId())); + register("wolf_variant", cache -> cache.wolfVariants, ($, entry) -> WolfEntity.BuiltInWolfVariant.getByJavaIdentifier(entry.getId().asString())); // Load from MCProtocolLib's classloader NbtMap tag = MinecraftProtocol.loadNetworkCodec(); - Map> defaults = new HashMap<>(); + Map> defaults = new HashMap<>(); // Don't create a keySet - no need to create the cached object in HashMap if we don't use it again REGISTRIES.forEach((key, $) -> { - List rawValues = tag.getCompound(key) + List rawValues = tag.getCompound(key.asString()) .getList("value", NbtType.COMPOUND); Map values = new HashMap<>(); for (NbtMap value : rawValues) { @@ -148,7 +150,7 @@ public final class RegistryCache { * @param the class that represents these entries. */ private static void register(String registry, Function> localCacheFunction, BiFunction reader) { - String key = "minecraft:" + registry; + Key key = MinecraftKey.key(registry); REGISTRIES.put(key, (registryCache, entries) -> { Map localRegistry = null; JavaRegistry localCache = localCacheFunction.apply(registryCache); @@ -176,7 +178,7 @@ public final class RegistryCache { * @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) -> { + REGISTRIES.put(MinecraftKey.key(registry), (registryCache, entries) -> { Int2IntMap temp = new Int2IntOpenHashMap(); int greatestId = 0; for (int i = 0; i < entries.size(); 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 656a16cf4..c8bfc7eed 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 @@ -26,6 +26,7 @@ package org.geysermc.geyser.session.cache; import it.unimi.dsi.fastutil.ints.IntArrays; +import net.kyori.adventure.key.Key; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserLogger; @@ -36,6 +37,7 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.BlockTag; import org.geysermc.geyser.session.cache.tags.EnchantmentTag; import org.geysermc.geyser.session.cache.tags.ItemTag; +import org.geysermc.geyser.util.MinecraftKey; import org.geysermc.geyser.util.Ordered; import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundUpdateTagsPacket; @@ -58,33 +60,33 @@ public final class TagCache { private final int[][] enchantments = new int[ALL_ENCHANTMENT_TAGS.size()][]; public void loadPacket(GeyserSession session, ClientboundUpdateTagsPacket packet) { - Map blockTags = packet.getTags().get("minecraft:block"); + Map blockTags = packet.getTags().get(MinecraftKey.key("block")); loadTags("Block", blockTags, ALL_BLOCK_TAGS, this.blocks); // Hack btw GeyserLogger logger = session.getGeyser().getLogger(); - int[] convertableToMud = blockTags.get("minecraft:convertable_to_mud"); + int[] convertableToMud = blockTags.get(MinecraftKey.key("convertable_to_mud")); boolean emulatePost1_18Logic = convertableToMud != null && convertableToMud.length != 0; session.setEmulatePost1_18Logic(emulatePost1_18Logic); if (logger.isDebug()) { logger.debug("Emulating post 1.18 block predication logic for " + session.bedrockUsername() + "? " + emulatePost1_18Logic); } - Map itemTags = packet.getTags().get("minecraft:item"); + Map itemTags = packet.getTags().get(MinecraftKey.key("item")); loadTags("Item", itemTags, ALL_ITEM_TAGS, this.items); // Hack btw - boolean emulatePost1_13Logic = itemTags.get("minecraft:signs").length > 1; + boolean emulatePost1_13Logic = itemTags.get(MinecraftKey.key("signs")).length > 1; session.setEmulatePost1_13Logic(emulatePost1_13Logic); if (logger.isDebug()) { logger.debug("Emulating post 1.13 villager logic for " + session.bedrockUsername() + "? " + emulatePost1_13Logic); } - Map enchantmentTags = packet.getTags().get("minecraft:enchantment"); + Map enchantmentTags = packet.getTags().get(MinecraftKey.key("enchantment")); loadTags("Enchantment", enchantmentTags, ALL_ENCHANTMENT_TAGS, this.enchantments); } - private void loadTags(String type, @Nullable Map packetTags, Map allTags, int[][] localValues) { + private void loadTags(String type, @Nullable Map packetTags, Map allTags, int[][] localValues) { if (packetTags == null) { Arrays.fill(localValues, IntArrays.EMPTY_ARRAY); GeyserImpl.getInstance().getLogger().debug("Not loading " + type + " tags; they do not exist here."); 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 index 5a85efc84..1dca7843a 100644 --- 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 @@ -25,6 +25,7 @@ package org.geysermc.geyser.session.cache.tags; +import net.kyori.adventure.key.Key; import org.geysermc.geyser.util.Ordered; import java.util.HashMap; @@ -32,7 +33,7 @@ import java.util.Map; @SuppressWarnings("unused") public final class BlockTag implements Ordered { - public static final Map ALL_BLOCK_TAGS = new HashMap<>(); + public static final Map ALL_BLOCK_TAGS = new HashMap<>(); public static final BlockTag WOOL = new BlockTag("wool"); public static final BlockTag PLANKS = new BlockTag("planks"); @@ -232,6 +233,6 @@ public final class BlockTag implements Ordered { } private static void register(String name, BlockTag tag) { - ALL_BLOCK_TAGS.put(("minecraft:" + name).intern(), tag); + ALL_BLOCK_TAGS.put(Key.key(name), tag); } } diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/tags/EnchantmentTag.java b/core/src/main/java/org/geysermc/geyser/session/cache/tags/EnchantmentTag.java index 3c5446adc..0af690abd 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/tags/EnchantmentTag.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/tags/EnchantmentTag.java @@ -25,6 +25,8 @@ package org.geysermc.geyser.session.cache.tags; +import net.kyori.adventure.key.Key; +import org.geysermc.geyser.util.MinecraftKey; import org.geysermc.geyser.util.Ordered; import java.util.HashMap; @@ -32,7 +34,7 @@ import java.util.Map; @SuppressWarnings("unused") public final class EnchantmentTag implements Ordered { - public static final Map ALL_ENCHANTMENT_TAGS = new HashMap<>(); + public static final Map ALL_ENCHANTMENT_TAGS = new HashMap<>(); public static final EnchantmentTag TOOLTIP_ORDER = new EnchantmentTag("tooltip_order"); public static final EnchantmentTag EXCLUSIVE_SET_ARMOR = new EnchantmentTag("exclusive_set/armor"); @@ -84,6 +86,6 @@ public final class EnchantmentTag implements Ordered { } private static void register(String name, EnchantmentTag tag) { - ALL_ENCHANTMENT_TAGS.put(("minecraft:" + name).intern(), tag); + ALL_ENCHANTMENT_TAGS.put(MinecraftKey.key(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 index e1fbf4634..a2e861dd6 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 @@ -25,6 +25,8 @@ package org.geysermc.geyser.session.cache.tags; +import net.kyori.adventure.key.Key; +import org.geysermc.geyser.util.MinecraftKey; import org.geysermc.geyser.util.Ordered; import java.util.HashMap; @@ -32,7 +34,7 @@ import java.util.Map; @SuppressWarnings("unused") public final class ItemTag implements Ordered { - public static final Map ALL_ITEM_TAGS = new HashMap<>(); + public static final Map ALL_ITEM_TAGS = new HashMap<>(); public static final ItemTag WOOL = new ItemTag("wool"); public static final ItemTag PLANKS = new ItemTag("planks"); @@ -195,6 +197,6 @@ public final class ItemTag implements Ordered { } private static void register(String name, ItemTag tag) { - ALL_ITEM_TAGS.put(("minecraft:" + name).intern(), tag); + ALL_ITEM_TAGS.put(MinecraftKey.key(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 d70f53e2c..166089b6b 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 @@ -45,7 +45,7 @@ import org.geysermc.geyser.session.GeyserSession; public class BiomeTranslator { public static int loadServerBiome(RegistryEntry entry) { - String javaIdentifier = entry.getId(); + String javaIdentifier = entry.getId().asString(); return Registries.BIOME_IDENTIFIERS.get().getOrDefault(javaIdentifier, 0); } 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 b5e923ee6..a7e4bc656 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,6 +25,7 @@ package org.geysermc.geyser.translator.protocol.bedrock; +import org.geysermc.geyser.util.MinecraftKey; 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; @@ -119,7 +120,8 @@ public class BedrockBlockEntityDataTranslator extends PacketTranslator { 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 1ecc5bf82..ecfb2d220 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 @@ -34,6 +34,7 @@ import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; import lombok.Getter; import lombok.ToString; +import net.kyori.adventure.key.Key; import net.kyori.adventure.text.format.NamedTextColor; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.cloudburstmc.protocol.bedrock.data.command.*; @@ -66,7 +67,7 @@ public class JavaCommandsTranslator extends PacketTranslator ALL_BLOCK_NAMES = Suppliers.memoize(() -> BlockRegistries.JAVA_BLOCKS.get().stream().map(block -> block.javaIdentifier().toString()).toArray(String[]::new)); private static final String[] ALL_EFFECT_IDENTIFIERS = EntityUtils.getAllEffectIdentifiers(); - private static final String[] ATTRIBUTES = AttributeType.Builtin.BUILTIN.values().stream().map(AttributeType::getIdentifier).toList().toArray(new String[0]); + private static final String[] ATTRIBUTES = AttributeType.Builtin.BUILTIN.values().stream().map(type -> type.getIdentifier().asString()).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; @@ -264,8 +265,8 @@ public class JavaCommandsTranslator extends PacketTranslator ATTRIBUTES; case "minecraft:enchantment" -> context.getEnchantments(); case "minecraft:entity_type" -> context.getEntityTypes(); @@ -476,12 +477,8 @@ public class JavaCommandsTranslator extends PacketTranslator { @@ -98,7 +101,7 @@ public class JavaLoginTranslator extends PacketTranslator bedrockRecipeIDs = context.translateShapelessRecipe(new GeyserShapelessRecipe(shapelessRecipeData)); if (bedrockRecipeIDs != null) { - context.addRecipeIdentifier(session, recipe.getIdentifier(), bedrockRecipeIDs); + context.addRecipeIdentifier(session, recipe.getIdentifier().asString(), bedrockRecipeIDs); } } case CRAFTING_SHAPED -> { ShapedRecipeData shapedRecipeData = (ShapedRecipeData) recipe.getData(); List bedrockRecipeIDs = context.translateShapedRecipe(new GeyserShapedRecipe(shapedRecipeData)); if (bedrockRecipeIDs != null) { - context.addRecipeIdentifier(session, recipe.getIdentifier(), bedrockRecipeIDs); + context.addRecipeIdentifier(session, recipe.getIdentifier().asString(), bedrockRecipeIDs); } } case STONECUTTING -> { @@ -160,7 +160,7 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator // similar as above "minecraft:arrow"; - default -> recipe.getIdentifier(); + default -> recipe.getIdentifier().asString(); }; addRecipeIdentifier(session, javaRecipeID, identifiers); 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 342618ff8..7c8374500 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 @@ -35,6 +35,6 @@ public class JavaStoreCookieTranslator extends PacketTranslator Date: Wed, 12 Jun 2024 23:53:02 -0400 Subject: [PATCH 088/233] Fix compilation for modded --- .../geyser/platform/mod/world/GeyserModWorldManager.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 5543dbcee..ef8c3ec0a 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 @@ -47,6 +47,7 @@ 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.MinecraftKey; 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; @@ -173,7 +174,7 @@ public class GeyserModWorldManager extends GeyserWorldManager { return patternLayers.layers().stream() .map(layer -> { BannerPatternLayer.BannerPattern pattern = new BannerPatternLayer.BannerPattern( - layer.pattern().value().assetId().toString(), layer.pattern().value().translationKey() + MinecraftKey.key(layer.pattern().value().assetId().toString()), layer.pattern().value().translationKey() ); return new BannerPatternLayer(Holder.ofCustom(pattern), layer.color().getId()); }) From d00cab18fdc0eeb15381cc17c384fd2f5a6faa88 Mon Sep 17 00:00:00 2001 From: chris Date: Thu, 13 Jun 2024 14:14:57 +0200 Subject: [PATCH 089/233] Only translate double chest tags if we are dealing with a double chest (#4736) --- .../block/entity/DoubleChestBlockEntityTranslator.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) 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 988d94073..9f111788b 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 @@ -42,9 +42,11 @@ public class DoubleChestBlockEntityTranslator extends BlockEntityTranslator impl @Override public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) { - int x = (int) bedrockNbt.get("x"); - int z = (int) bedrockNbt.get("z"); - translateChestValue(bedrockNbt, blockState, x, z); + if (blockState.getValue(Properties.CHEST_TYPE) != ChestType.SINGLE) { + int x = (int) bedrockNbt.get("x"); + int z = (int) bedrockNbt.get("z"); + translateChestValue(bedrockNbt, blockState, x, z); + } } /** From db5a5289659d8b07abdcca83e5549672ddc0e272 Mon Sep 17 00:00:00 2001 From: chris Date: Thu, 13 Jun 2024 16:53:01 +0200 Subject: [PATCH 090/233] Fix: Improper detection of virtual double chests (#4738) --- .../inventory/chest/DoubleChestInventoryTranslator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 06531eff2..856cc1876 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 @@ -64,7 +64,7 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator { if (session.getLastInteractionPlayerPosition().equals(session.getPlayerEntity().getPosition())) { BlockState state = session.getGeyser().getWorldManager().blockAt(session, session.getLastInteractionBlockPosition()); if (!BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get().containsKey(state.javaId())) { - if (state.block() == Blocks.CHEST || state.block() == Blocks.TRAPPED_CHEST + if ((state.block() == Blocks.CHEST || state.block() == Blocks.TRAPPED_CHEST) && state.getValue(Properties.CHEST_TYPE) != ChestType.SINGLE) { inventory.setHolderPosition(session.getLastInteractionBlockPosition()); ((Container) inventory).setUsingRealBlock(true, state.block()); From ce3083b9b83b65ffc041326e45f14aa040c9dd7b Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Thu, 13 Jun 2024 11:24:16 -0400 Subject: [PATCH 091/233] Fix key regression with pre-built registries --- .../geysermc/geyser/session/cache/RegistryCache.java | 10 +++++----- .../java/JavaClientboundRecipesTranslator.java | 1 - 2 files changed, 5 insertions(+), 6 deletions(-) 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 02c43939d..3121af369 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 @@ -72,7 +72,7 @@ import java.util.function.ToIntFunction; @Accessors(fluent = true) @Getter public final class RegistryCache { - private static final Map> DEFAULTS; + private static final Map> DEFAULTS; private static final Map>> REGISTRIES = new HashMap<>(); static { @@ -89,14 +89,14 @@ public final class RegistryCache { // Load from MCProtocolLib's classloader NbtMap tag = MinecraftProtocol.loadNetworkCodec(); - Map> defaults = new HashMap<>(); + Map> defaults = new HashMap<>(); // Don't create a keySet - no need to create the cached object in HashMap if we don't use it again REGISTRIES.forEach((key, $) -> { List rawValues = tag.getCompound(key.asString()) .getList("value", NbtType.COMPOUND); - Map values = new HashMap<>(); + Map values = new HashMap<>(); for (NbtMap value : rawValues) { - String name = value.getString("name"); + Key name = MinecraftKey.key(value.getString("name")); values.put(name, value.getCompound("element")); } // Can make these maps immutable and as efficient as possible after initialization @@ -152,7 +152,7 @@ public final class RegistryCache { private static void register(String registry, Function> localCacheFunction, BiFunction reader) { Key key = MinecraftKey.key(registry); REGISTRIES.put(key, (registryCache, entries) -> { - Map localRegistry = null; + Map localRegistry = null; JavaRegistry localCache = localCacheFunction.apply(registryCache); // Clear each local cache every time a new registry entry is given to us // (e.g. proxy server switches) 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 06abbbac0..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 @@ -39,7 +39,6 @@ public class JavaClientboundRecipesTranslator extends PacketTranslator { From 746be566a2a341498b27ace99a079f6db4adb5d5 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Thu, 13 Jun 2024 13:53:20 -0400 Subject: [PATCH 092/233] Sanity check for BlockState being chest --- .../level/block/entity/DoubleChestBlockEntityTranslator.java | 4 ++++ 1 file changed, 4 insertions(+) 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 9f111788b..6fea10e2e 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 @@ -27,6 +27,7 @@ package org.geysermc.geyser.translator.level.block.entity; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; +import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.level.block.property.ChestType; import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.level.block.type.BlockState; @@ -42,6 +43,9 @@ public class DoubleChestBlockEntityTranslator extends BlockEntityTranslator impl @Override public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) { + if (!(blockState.is(Blocks.CHEST) || blockState.is(Blocks.TRAPPED_CHEST))) { + return; + } if (blockState.getValue(Properties.CHEST_TYPE) != ChestType.SINGLE) { int x = (int) bedrockNbt.get("x"); int z = (int) bedrockNbt.get("z"); From b6653acc294e21778d09bfa155528bf116eea70c Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Thu, 13 Jun 2024 19:53:47 +0200 Subject: [PATCH 093/233] Catch Throwable when trying to load world adapter --- .../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 d138ad074..fdef77bbe 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 @@ -265,7 +265,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { this.geyserWorldManager = new GeyserSpigotNativeWorldManager(this, isPaper); } geyserLogger.debug("Using world manager of type: " + this.geyserWorldManager.getClass().getSimpleName()); - } catch (Exception e) { + } catch (Throwable e) { if (geyserConfig.isDebugMode()) { geyserLogger.debug("Error while attempting to find NMS adapter. Most likely, this can be safely ignored. :)"); e.printStackTrace(); From a5ecee73ef0f4382420ffd252eb2097ba70d4e3b Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Thu, 13 Jun 2024 20:12:45 +0200 Subject: [PATCH 094/233] Update Bungee warning for outdated proxy checks --- .../geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 062ef6f76..cd6b59f64 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 @@ -81,7 +81,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_5"); + ProtocolConstants.class.getField("MINECRAFT_1_21"); } catch (NoSuchFieldException e) { geyserLogger.error(" / \\"); geyserLogger.error(" / \\"); From 4a334a2c8d7068c84fc9d41ada97a86f77c85c1f Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Thu, 13 Jun 2024 14:58:39 -0400 Subject: [PATCH 095/233] Bed block sanity check for villagers --- .../type/living/merchant/VillagerEntity.java | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 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 fb07572e6..d7efa9f1d 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 @@ -34,6 +34,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.packet.MoveEntityAbsolutePacket; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.geyser.level.block.type.BedBlock; import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; @@ -125,22 +126,24 @@ public class VillagerEntity extends AbstractMerchantEntity { int bedRotation = 0; float xOffset = 0; float zOffset = 0; - switch (state.getValue(Properties.HORIZONTAL_FACING)) { - case SOUTH -> { - bedRotation = 180; - zOffset = -.5f; - } - case EAST -> { - bedRotation = 90; - xOffset = -.5f; - } - case WEST -> { - bedRotation = 270; - xOffset = .5f; - } - case NORTH -> { - // rotation does not change because north is 0 - zOffset = .5f; + if (state.block() instanceof BedBlock) { + switch (state.getValue(Properties.HORIZONTAL_FACING)) { + case SOUTH -> { + bedRotation = 180; + zOffset = -.5f; + } + case EAST -> { + bedRotation = 90; + xOffset = -.5f; + } + case WEST -> { + bedRotation = 270; + xOffset = .5f; + } + case NORTH -> { + // rotation does not change because north is 0 + zOffset = .5f; + } } } From 6a715770e21d0569d00e50b8ab4eea7a9c8518be Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Thu, 13 Jun 2024 23:20:43 +0200 Subject: [PATCH 096/233] Update mod dependencies to their official 1.21 releases --- .../mod/fabric/src/main/resources/fabric.mod.json | 4 ++-- .../src/main/resources/META-INF/neoforge.mods.toml | 4 ++-- .../main/kotlin/geyser.modded-conventions.gradle.kts | 10 ++-------- gradle/libs.versions.toml | 4 ++-- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/bootstrap/mod/fabric/src/main/resources/fabric.mod.json b/bootstrap/mod/fabric/src/main/resources/fabric.mod.json index 93f48b73c..262f9833a 100644 --- a/bootstrap/mod/fabric/src/main/resources/fabric.mod.json +++ b/bootstrap/mod/fabric/src/main/resources/fabric.mod.json @@ -23,8 +23,8 @@ "geyser.mixins.json" ], "depends": { - "fabricloader": ">=0.15.10", + "fabricloader": ">=0.15.11", "fabric": "*", - "minecraft": ">=1.20.5" + "minecraft": ">=1.21" } } diff --git a/bootstrap/mod/neoforge/src/main/resources/META-INF/neoforge.mods.toml b/bootstrap/mod/neoforge/src/main/resources/META-INF/neoforge.mods.toml index 3a25f6119..fa01bb6ec 100644 --- a/bootstrap/mod/neoforge/src/main/resources/META-INF/neoforge.mods.toml +++ b/bootstrap/mod/neoforge/src/main/resources/META-INF/neoforge.mods.toml @@ -14,12 +14,12 @@ config = "geyser.mixins.json" [[dependencies.geyser_neoforge]] modId="neoforge" type="required" - versionRange="[20.5.0-beta,)" + versionRange="[21.0.0-beta,)" ordering="NONE" side="BOTH" [[dependencies.geyser_neoforge]] modId="minecraft" type="required" - versionRange="[1.20.5,)" + versionRange="[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 6472e4312..86c2a2f6a 100644 --- a/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts @@ -110,7 +110,7 @@ afterEvaluate { } dependencies { - minecraft("com.mojang:minecraft:1.21-rc1") + minecraft("com.mojang:minecraft:1.21") mappings(loom.officialMojangMappings()) } @@ -121,12 +121,6 @@ repositories { maven("https://oss.sonatype.org/content/repositories/snapshots/") maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") maven("https://maven.neoforged.net/releases") - maven("https://prmaven.neoforged.net/NeoForge/pr1076") { - name = "Maven for 1.21 PR" - content { - includeModule("net.neoforged", "neoforge") - } - } } modrinth { @@ -139,6 +133,6 @@ modrinth { syncBodyFrom.set(rootProject.file("README.md").readText()) uploadFile.set(tasks.getByPath("remapModrinthJar")) - gameVersions.addAll("1.20.5", "1.20.6") + gameVersions.addAll("1.21") failSilently.set(true) } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 10a94c3db..5e55aa117 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -28,11 +28,11 @@ commodore = "2.2" bungeecord = "a7c6ede" velocity = "3.3.0-SNAPSHOT" viaproxy = "3.2.1" -fabric-minecraft = "1.21-rc1" +fabric-minecraft = "1.21" fabric-loader = "0.15.11" fabric-api = "0.100.1+1.21" fabric-permissions = "0.2-SNAPSHOT" -neoforge-minecraft = "21.0.0-alpha.1.21-rc1.20240611.001314" +neoforge-minecraft = "21.0.0-beta" mixin = "0.8.5" # plugin versions From 09c0ada50216e1a163b22cccdce5b0657085ebd6 Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Thu, 13 Jun 2024 19:53:47 +0200 Subject: [PATCH 097/233] Catch Throwable when trying to load world adapter --- .../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 d138ad074..fdef77bbe 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 @@ -265,7 +265,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { this.geyserWorldManager = new GeyserSpigotNativeWorldManager(this, isPaper); } geyserLogger.debug("Using world manager of type: " + this.geyserWorldManager.getClass().getSimpleName()); - } catch (Exception e) { + } catch (Throwable e) { if (geyserConfig.isDebugMode()) { geyserLogger.debug("Error while attempting to find NMS adapter. Most likely, this can be safely ignored. :)"); e.printStackTrace(); From 138c7b4eee97670d36ec36f5bc0dc6cfcbab56fa Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 14 Jun 2024 17:27:30 +0200 Subject: [PATCH 098/233] Catch EOFExceptions while pinging Java servers when it is misconfigured/not online (#4746) * Catch EOFExceptions when the remote server is misconfigured/not online --- .../geysermc/geyser/ping/GeyserLegacyPingPassthrough.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 320334ee5..27b405348 100644 --- a/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java +++ b/core/src/main/java/org/geysermc/geyser/ping/GeyserLegacyPingPassthrough.java @@ -35,10 +35,7 @@ import org.cloudburstmc.nbt.util.VarInts; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.network.GameProtocol; -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; +import java.io.*; import java.net.*; import java.util.concurrent.TimeUnit; @@ -139,6 +136,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 (EOFException e) { + this.pingInfo = null; + this.geyser.getLogger().warning("Failed to ping the remote Java server! Is it online and configured in Geyser's config?"); } 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?"); From 28e4661fcf68f572c8ea5a60c7acb152f13b2ca4 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Fri, 14 Jun 2024 14:02:11 -0400 Subject: [PATCH 099/233] Fix incoming player chat --- .../main/java/org/geysermc/geyser/text/TextDecoration.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 cf2071173..ab9e2b5ed 100644 --- a/core/src/main/java/org/geysermc/geyser/text/TextDecoration.java +++ b/core/src/main/java/org/geysermc/geyser/text/TextDecoration.java @@ -50,13 +50,13 @@ public record TextDecoration(String translationKey, List parameters, NbtMap tag = entry.getData(); NbtMap chat = tag.getCompound("chat", null); if (chat != null) { - String translationKey = tag.getString("translation_key"); + String translationKey = chat.getString("translation_key"); - NbtMap styleTag = tag.getCompound("style"); + NbtMap styleTag = chat.getCompound("style"); Style style = deserializeStyle(styleTag); List parameters = new ArrayList<>(); - List parametersNbt = tag.getList("parameters", NbtType.STRING); + List parametersNbt = chat.getList("parameters", NbtType.STRING); for (String parameter : parametersNbt) { parameters.add(ChatTypeDecoration.Parameter.valueOf(parameter.toUpperCase(Locale.ROOT))); } From a9ba1ad603d819695c2aca7c6c83f2912d03ec98 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Fri, 14 Jun 2024 15:44:00 -0400 Subject: [PATCH 100/233] Properly translate ominous items --- .../java/org/geysermc/geyser/item/Items.java | 2 +- .../geysermc/geyser/item/type/ArrowItem.java | 5 ++ .../geyser/item/type/FireworkStarItem.java | 5 ++ .../geyser/item/type/GoatHornItem.java | 5 ++ .../org/geysermc/geyser/item/type/Item.java | 8 +++ .../geyser/item/type/OminousBottleItem.java | 72 +++++++++++++++++++ .../geysermc/geyser/item/type/PotionItem.java | 5 ++ .../registry/populator/Conversion685_671.java | 6 ++ .../geyser/registry/type/ItemMappings.java | 9 +-- core/src/main/resources/mappings | 2 +- 10 files changed, 111 insertions(+), 8 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/item/type/OminousBottleItem.java 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 5ae69fa4e..1ddd14982 100644 --- a/core/src/main/java/org/geysermc/geyser/item/Items.java +++ b/core/src/main/java/org/geysermc/geyser/item/Items.java @@ -1368,7 +1368,7 @@ public final class Items { 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(builder(), Blocks.VAULT)); - public static final Item OMINOUS_BOTTLE = register(new Item("ominous_bottle", builder())); + public static final Item OMINOUS_BOTTLE = register(new OminousBottleItem("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/ArrowItem.java b/core/src/main/java/org/geysermc/geyser/item/type/ArrowItem.java index c06a143ac..4e4f1830e 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 @@ -51,4 +51,9 @@ public class ArrowItem extends Item { } return itemStack; } + + @Override + public boolean ignoreDamage() { + return true; + } } 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 2ba9b4258..5ac0f475c 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 @@ -90,4 +90,9 @@ public class FireworkStarItem extends Item { components.put(DataComponentType.FIREWORK_EXPLOSION, newExplosion); } } + + @Override + public boolean ignoreDamage() { + return true; + } } 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 cd21c0b6e..d0e85ec52 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 @@ -62,4 +62,9 @@ public class GoatHornItem extends Item { return itemStack; } + + @Override + public boolean ignoreDamage() { + return true; + } } 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 3014e8116..0b2521a3e 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 @@ -226,6 +226,14 @@ public class Item { } } + /** + * Override if the Bedrock equivalent of an item uses damage for extra data, and should not be tracked + * when translating an item. + */ + public boolean ignoreDamage() { + return false; + } + /* Translation methods end */ public GeyserItemStack newItemStack(int count, DataComponents components) { diff --git a/core/src/main/java/org/geysermc/geyser/item/type/OminousBottleItem.java b/core/src/main/java/org/geysermc/geyser/item/type/OminousBottleItem.java new file mode 100644 index 000000000..815f71419 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/item/type/OminousBottleItem.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 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.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.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; + +public class OminousBottleItem extends Item { + public OminousBottleItem(String javaIdentifier, Builder builder) { + super(javaIdentifier, builder); + } + + @Override + public ItemData.Builder translateToBedrock(int count, @Nullable DataComponents components, ItemMapping mapping, ItemMappings mappings) { + var builder = super.translateToBedrock(count, components, mapping, mappings); + if (components == null) { + // Level 1 ominous bottle is null components - Java 1.21. + return builder; + } + Integer amplifier = components.get(DataComponentType.OMINOUS_BOTTLE_AMPLIFIER); + if (amplifier != null) { + builder.damage(amplifier); + } + return builder; + } + + @Override + public @NonNull GeyserItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) { + // This item can be pulled from the creative inventory with amplifiers. + GeyserItemStack itemStack = super.translateToJava(itemData, mapping, mappings); + int damage = itemData.getDamage(); + if (damage == 0) { + return itemStack; + } + itemStack.getOrCreateComponents().put(DataComponentType.OMINOUS_BOTTLE_AMPLIFIER, damage); + return itemStack; + } + + @Override + public boolean ignoreDamage() { + return true; + } +} 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 e9889c882..f8fe2b4ee 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 @@ -76,4 +76,9 @@ public class PotionItem extends Item { } return itemStack; } + + @Override + public boolean ignoreDamage() { + return true; + } } diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion685_671.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion685_671.java index 41a8af826..58886ca57 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion685_671.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion685_671.java @@ -50,6 +50,12 @@ public class Conversion685_671 { if (NEW_MUSIC_DISCS.contains(item)) { return mapping.withBedrockIdentifier("minecraft:music_disc_otherside"); } + if (item == Items.OMINOUS_TRIAL_KEY) { + return mapping.withBedrockIdentifier("minecraft:trial_key"); + } + if (item == Items.OMINOUS_BOTTLE) { + return mapping.withBedrockIdentifier("minecraft:glass_bottle"); + } if (!NEW_BLOCKS.contains(identifer)) { return mapping; 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 94c863660..189474238 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,6 @@ package org.geysermc.geyser.registry.type; -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; @@ -41,7 +40,7 @@ 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; -import org.geysermc.geyser.item.type.PotionItem; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import java.util.List; import java.util.Map; @@ -148,10 +147,8 @@ public class ItemMappings implements DefinitionRegistry { } } else { if (!(mapping.getBedrockData() == data.getDamage() || - // 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.SUSPICIOUS_STEW))) { + // Make exceptions for items whose damage values can vary + (mapping.getJavaItem().ignoreDamage() || mapping.getJavaItem() == Items.SUSPICIOUS_STEW))) { continue; } } diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings index 396ea5ff5..5f892d04d 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 396ea5ff50d8c976fde4e7423e682d21aa0ee350 +Subproject commit 5f892d04d2212a13fad3f517b3f516d6526833f2 From 7e87af718bab6e858fa8a6793a400c407edea9cf Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Fri, 14 Jun 2024 16:48:46 -0400 Subject: [PATCH 101/233] Fix item attribute modifiers --- .../org/geysermc/geyser/translator/item/ItemTranslator.java | 2 +- gradle/libs.versions.toml | 2 +- 2 files changed, 2 insertions(+), 2 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 8b61e435a..672d2d7a5 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 @@ -247,7 +247,7 @@ public final class ItemTranslator { return null; } - String name = modifier.getName().replace("minecraft:", ""); + String name = modifier.getId().asMinimalString(); // the namespace does not need to be present, but if it is, the java client ignores it as of pre-1.20.5 ModifierOperation operation = modifier.getOperation(); diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5e55aa117..1677d46fa 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ websocket = "1.5.1" protocol = "3.0.0.Beta2-20240606.172607-7" raknet = "1.0.0.CR3-20240416.144209-1" mcauthlib = "e5b0bcc" -mcprotocollib = "f9cc9ee6" +mcprotocollib = "dcf9d02" adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From be83fe7220f6679d0c558a3c0db78a4dabd54c7d Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Fri, 14 Jun 2024 19:36:10 -0400 Subject: [PATCH 102/233] Re-enable crafter inventory --- .../geysermc/geyser/inventory/Container.java | 2 +- .../geyser/inventory/CrafterContainer.java | 40 ++++++++++++++++++- .../inventory/InventoryTranslator.java | 2 +- .../JavaContainerSetContentTranslator.java | 3 +- core/src/main/resources/mappings | 2 +- 5 files changed, 43 insertions(+), 6 deletions(-) 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 81818613f..e78a4d2c6 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/Container.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/Container.java @@ -38,7 +38,7 @@ import org.jetbrains.annotations.Range; */ @Getter public class Container extends Inventory { - private final PlayerInventory playerInventory; + protected final PlayerInventory playerInventory; private final int containerSize; /** 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 41452bed6..fb118252d 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/CrafterContainer.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/CrafterContainer.java @@ -25,13 +25,19 @@ package org.geysermc.geyser.inventory; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.inventory.CrafterInventoryTranslator; +import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; import lombok.Getter; import lombok.Setter; import org.geysermc.geyser.GeyserImpl; +import org.jetbrains.annotations.Range; @Getter public class CrafterContainer extends Container { + private GeyserItemStack resultItem = GeyserItemStack.EMPTY; @Setter private boolean triggered = false; @@ -46,8 +52,36 @@ public class CrafterContainer extends Container { super(title, id, size, containerType, playerInventory); } + @Override + public GeyserItemStack getItem(int slot) { + if (slot == CrafterInventoryTranslator.JAVA_RESULT_SLOT) { + return this.resultItem; + } else if (isCraftingGrid(slot)) { + return super.getItem(slot); + } else { + return playerInventory.getItem(slot - CrafterInventoryTranslator.GRID_SIZE + InventoryTranslator.PLAYER_INVENTORY_OFFSET); + } + } + + @Override + public int getOffsetForHotbar(@Range(from = 0, to = 8) int slot) { + return playerInventory.getOffsetForHotbar(slot) - InventoryTranslator.PLAYER_INVENTORY_OFFSET + CrafterInventoryTranslator.GRID_SIZE; + } + + @Override + public void setItem(int slot, @NonNull GeyserItemStack newItem, GeyserSession session) { + if (slot == CrafterInventoryTranslator.JAVA_RESULT_SLOT) { + // Result item probably won't be an item that needs to worry about net ID or lodestone compasses + this.resultItem = newItem; + } else if (isCraftingGrid(slot)) { + super.setItem(slot, newItem, session); + } else { + playerInventory.setItem(slot - CrafterInventoryTranslator.GRID_SIZE + InventoryTranslator.PLAYER_INVENTORY_OFFSET, newItem, session); + } + } + public void setSlot(int slot, boolean enabled) { - if (slot < 0 || slot > 8) { + if (!isCraftingGrid(slot)) { GeyserImpl.getInstance().getLogger().warning("Crafter slot out of bounds: " + slot); return; } @@ -58,4 +92,8 @@ public class CrafterContainer extends Container { disabledSlotsMask = (short) (disabledSlotsMask | (1 << slot)); } } + + private static boolean isCraftingGrid(int slot) { + return slot >= 0 && slot <= 8; + } } 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 5e4ffcafd..4c426b410 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()); todo Output slot is currently broken + 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/protocol/java/inventory/JavaContainerSetContentTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetContentTranslator.java index 44bd7171f..36d382d69 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,8 +25,6 @@ package org.geysermc.geyser.translator.protocol.java.inventory; -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; import org.geysermc.geyser.inventory.Inventory; @@ -36,6 +34,7 @@ import org.geysermc.geyser.translator.inventory.PlayerInventoryTranslator; 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.ClientboundContainerSetContentPacket; @Translator(packet = ClientboundContainerSetContentPacket.class) public class JavaContainerSetContentTranslator extends PacketTranslator { diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings index 5f892d04d..2ac0c1415 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 5f892d04d2212a13fad3f517b3f516d6526833f2 +Subproject commit 2ac0c1415cb9063c405dbd7e14f2d426a0ba1180 From b1d319bb7eb394c208b91ffbf91d3a20198fa271 Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Sat, 15 Jun 2024 18:39:09 +0200 Subject: [PATCH 103/233] Add Spigot 1.21 world adapter --- .../org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java | 1 + gradle/libs.versions.toml | 2 +- 2 files changed, 2 insertions(+), 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 fdef77bbe..2d13155f2 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 @@ -251,6 +251,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { SpigotAdapters.registerWorldAdapter(nmsVersion); geyserLogger.debug("Using spigot NMS adapter for nms version: " + nmsVersion); } catch (Exception e) { // Likely running on Paper 1.20.5+ + geyserLogger.debug("Unable to find spigot world manager: " + e.getMessage()); //noinspection deprecation int protocolVersion = Bukkit.getUnsafe().getProtocolVersion(); PaperAdapters.registerClosestWorldAdapter(protocolVersion); diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1677d46fa..648d5eb03 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.9.2" -adapters = "1.12-SNAPSHOT" +adapters = "1.13-SNAPSHOT" commodore = "2.2" bungeecord = "a7c6ede" velocity = "3.3.0-SNAPSHOT" From 851ed36244b733dcf1c24374a4a747740f2251aa Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sat, 15 Jun 2024 16:52:09 -0400 Subject: [PATCH 104/233] Translate vault block entity --- .../entity/VaultBlockEntityTranslator.java | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 core/src/main/java/org/geysermc/geyser/translator/level/block/entity/VaultBlockEntityTranslator.java diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/VaultBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/VaultBlockEntityTranslator.java new file mode 100644 index 000000000..5f39451ac --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/VaultBlockEntityTranslator.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 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 it.unimi.dsi.fastutil.longs.LongArrayList; +import it.unimi.dsi.fastutil.longs.LongList; +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.entity.type.player.PlayerEntity; +import org.geysermc.geyser.level.block.type.BlockState; +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; +import java.util.UUID; + +@BlockEntity(type = BlockEntityType.VAULT) +public class VaultBlockEntityTranslator extends BlockEntityTranslator { + // Bedrock 1.21 does not send the position nor ID in the tag. + @Override + public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, @Nullable NbtMap javaNbt, BlockState blockState) { + NbtMapBuilder builder = NbtMap.builder(); + if (javaNbt != null) { + translateTag(session, builder, javaNbt, blockState); + } + return builder.build(); + } + + @Override + public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) { + NbtMap sharedData = javaNbt.getCompound("shared_data"); + + NbtMap item = sharedData.getCompound("display_item"); + ItemMapping mapping = session.getItemMappings().getMapping(item.getString("id")); + if (mapping == null) { + bedrockNbt.putCompound("display_item", NbtMap.builder() + .putByte("Count", (byte) 0) + .putShort("Damage", (short) 0) + .putString("Name", "") + .putByte("WasPickedUp", (byte) 0).build()); + } else { + int count = item.getInt("count"); + NbtMapBuilder bedrockItem = BedrockItemBuilder.createItemNbt(mapping, count, mapping.getBedrockData()); + // TODO handle components... + bedrockNbt.putCompound("display_item", bedrockItem.build()); + } + + List connectedPlayers = sharedData.getList("connected_players", NbtType.INT_ARRAY); + LongList bedrockPlayers = new LongArrayList(connectedPlayers.size()); + for (int[] player : connectedPlayers) { + UUID uuid = uuidFromIntArray(player); + PlayerEntity playerEntity = session.getEntityCache().getPlayerEntity(uuid); + if (playerEntity != null) { + bedrockPlayers.add(playerEntity.getGeyserId()); + } + } + bedrockNbt.putList("connected_players", NbtType.LONG, bedrockPlayers); + + // Fill this in, since as of Java 1.21, Bedrock always seems to include it, but Java assumes the default + // if it is not sent over the network + bedrockNbt.putFloat("connected_particle_range", (float) sharedData.getDouble("connected_particles_range", 4.5d)); + } + + // From ViaVersion! thank u!! + private static UUID uuidFromIntArray(int[] parts) { + return new UUID((long) parts[0] << 32 | (parts[1] & 0xFFFFFFFFL), (long) parts[2] << 32 | (parts[3] & 0xFFFFFFFFL)); + } +} From 6025931c7d7728f104676f3bacfd898f3d64fcb2 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sat, 15 Jun 2024 22:40:29 -0400 Subject: [PATCH 105/233] Properly translate player entity UUID for vaults --- .../level/block/entity/VaultBlockEntityTranslator.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/VaultBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/VaultBlockEntityTranslator.java index 5f39451ac..50fd64202 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/VaultBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/VaultBlockEntityTranslator.java @@ -76,9 +76,13 @@ public class VaultBlockEntityTranslator extends BlockEntityTranslator { LongList bedrockPlayers = new LongArrayList(connectedPlayers.size()); for (int[] player : connectedPlayers) { UUID uuid = uuidFromIntArray(player); - PlayerEntity playerEntity = session.getEntityCache().getPlayerEntity(uuid); - if (playerEntity != null) { - bedrockPlayers.add(playerEntity.getGeyserId()); + if (uuid.equals(session.getPlayerEntity().getUuid())) { + bedrockPlayers.add(session.getPlayerEntity().getGeyserId()); + } else { + PlayerEntity playerEntity = session.getEntityCache().getPlayerEntity(uuid); + if (playerEntity != null) { + bedrockPlayers.add(playerEntity.getGeyserId()); + } } } bedrockNbt.putList("connected_players", NbtType.LONG, bedrockPlayers); From bd30b34600938f7dbea91ce36889a6605959543c Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Sun, 16 Jun 2024 01:06:17 -0400 Subject: [PATCH 106/233] Bump MCPL --- 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 648d5eb03..6beae8f8d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ websocket = "1.5.1" protocol = "3.0.0.Beta2-20240606.172607-7" raknet = "1.0.0.CR3-20240416.144209-1" mcauthlib = "e5b0bcc" -mcprotocollib = "dcf9d02" +mcprotocollib = "4f5f650" adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From d9f9fcf39a784b1ccb642712668acec5741e729b Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sun, 16 Jun 2024 12:26:31 -0400 Subject: [PATCH 107/233] Bump Protocol --- 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 6beae8f8d..1456a7e34 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,7 @@ 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" -protocol = "3.0.0.Beta2-20240606.172607-7" +protocol = "3.0.0.Beta2-20240616.144648-10" raknet = "1.0.0.CR3-20240416.144209-1" mcauthlib = "e5b0bcc" mcprotocollib = "4f5f650" From 6cda7c2202716525f525dff7f8efa00b5e0949ea Mon Sep 17 00:00:00 2001 From: YHDiamond <47502993+YHDiamond@users.noreply.github.com> Date: Sun, 16 Jun 2024 15:01:21 -0400 Subject: [PATCH 108/233] Partially implement handling of "hide_tooltip" and fix attribute modifiers in "Armor" category not showing (#4731) * Skip lore creation if hide tooltips exists * Fix not showing attributes for "Armor" category * Minor refactor --------- Co-authored-by: chris --- .../org/geysermc/geyser/item/type/Item.java | 2 +- .../translator/item/ItemTranslator.java | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) 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 0b2521a3e..362b760c7 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 @@ -125,7 +125,7 @@ public class Item { */ public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) { List loreComponents = components.get(DataComponentType.LORE); - if (loreComponents != null) { + if (loreComponents != null && components.get(DataComponentType.HIDE_TOOLTIP) == null) { List lore = builder.getOrCreateLore(); for (Component loreComponent : loreComponents) { lore.add(MessageTranslator.convertMessage(loreComponent, session.locale())); 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 672d2d7a5..7572f5e61 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 @@ -65,6 +65,12 @@ public final class ItemTranslator { * The order of these slots is their display order on Java Edition clients */ private static final EnumMap SLOT_NAMES; + private static final ItemAttributeModifiers.EquipmentSlotGroup[] ARMOR_SLOT_NAMES = new ItemAttributeModifiers.EquipmentSlotGroup[] { + ItemAttributeModifiers.EquipmentSlotGroup.HEAD, + ItemAttributeModifiers.EquipmentSlotGroup.CHEST, + ItemAttributeModifiers.EquipmentSlotGroup.LEGS, + ItemAttributeModifiers.EquipmentSlotGroup.FEET + }; private static final DecimalFormat ATTRIBUTE_FORMAT = new DecimalFormat("0.#####"); static { @@ -132,8 +138,10 @@ public final class ItemTranslator { private static ItemData.@NonNull Builder translateToBedrock(GeyserSession session, Item javaItem, ItemMapping bedrockItem, int count, @Nullable DataComponents components) { BedrockItemBuilder nbtBuilder = new BedrockItemBuilder(); + boolean hideTooltips = false; if (components != null) { javaItem.translateComponentsToBedrock(session, components, nbtBuilder); + if (components.get(DataComponentType.HIDE_TOOLTIP) != null) hideTooltips = true; } String customName = getCustomName(session, components, bedrockItem); @@ -143,13 +151,13 @@ public final class ItemTranslator { if (components != null) { ItemAttributeModifiers attributeModifiers = components.get(DataComponentType.ATTRIBUTE_MODIFIERS); - if (attributeModifiers != null && attributeModifiers.isShowInTooltip()) { + if (attributeModifiers != null && attributeModifiers.isShowInTooltip() && !hideTooltips) { // only add if attribute modifiers do not indicate to hide them addAttributeLore(attributeModifiers, nbtBuilder, session.locale()); } } - if (session.isAdvancedTooltips()) { + if (session.isAdvancedTooltips() && !hideTooltips) { addAdvancedTooltips(components, nbtBuilder, javaItem, session.locale()); } @@ -207,7 +215,12 @@ public final class ItemTranslator { } ItemAttributeModifiers.EquipmentSlotGroup slotGroup = entry.getSlot(); - if (slotGroup == ItemAttributeModifiers.EquipmentSlotGroup.ANY) { + if (slotGroup == ItemAttributeModifiers.EquipmentSlotGroup.ARMOR) { + // modifier applies to all armor slots + for (ItemAttributeModifiers.EquipmentSlotGroup slot : ARMOR_SLOT_NAMES) { + slotsToModifiers.computeIfAbsent(slot, s -> new ArrayList<>()).add(loreEntry); + } + } else if (slotGroup == ItemAttributeModifiers.EquipmentSlotGroup.ANY) { // modifier applies to all slots implicitly for (var slot : SLOT_NAMES.keySet()) { slotsToModifiers.computeIfAbsent(slot, s -> new ArrayList<>()).add(loreEntry); From 1efb633723f601ce4130df8a0ca9dc3a4fe321e6 Mon Sep 17 00:00:00 2001 From: basaigh <53559772+basaigh@users.noreply.github.com> Date: Sun, 16 Jun 2024 22:05:28 +0100 Subject: [PATCH 109/233] Bump MCPL (#4756) --- .../java/level/JavaLevelEventTranslator.java | 52 +++++++++---------- core/src/main/resources/mappings | 2 +- gradle/libs.versions.toml | 4 +- 3 files changed, 29 insertions(+), 29 deletions(-) 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 2d3bca0d4..d4e317af4 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 @@ -57,7 +57,7 @@ public class JavaLevelEventTranslator extends PacketTranslator { + case PARTICLES_AND_SOUND_BRUSH_BLOCK_COMPLETE -> { effectPacket.setType(ParticleType.BRUSH_DUST); session.playSoundEvent(SoundEvent.BRUSH_COMPLETED, pos); // todo 1.20.2 verify this } - case COMPOSTER -> { + case COMPOSTER_FILL -> { effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_CROP_GROWTH); ComposterEventData composterEventData = (ComposterEventData) packet.getData(); @@ -146,7 +146,7 @@ public class JavaLevelEventTranslator extends PacketTranslator { + case LAVA_FIZZ -> { effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_EVAPORATE); effectPacket.setPosition(pos.add(-0.5f, 0.7f, -0.5f)); @@ -159,7 +159,7 @@ public class JavaLevelEventTranslator extends PacketTranslator { + case REDSTONE_TORCH_BURNOUT -> { effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_EVAPORATE); effectPacket.setPosition(pos.add(-0.5f, 0, -0.5f)); @@ -172,7 +172,7 @@ public class JavaLevelEventTranslator extends PacketTranslator { + case END_PORTAL_FRAME_FILL -> { effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_EVAPORATE); effectPacket.setPosition(pos.add(-0.5f, 0.3125f, -0.5f)); @@ -185,8 +185,8 @@ public class JavaLevelEventTranslator extends PacketTranslator { - if (levelEvent == LevelEventType.SMOKE) { + case PARTICLES_SHOOT_SMOKE, PARTICLES_SHOOT_WHITE_SMOKE -> { + if (levelEvent == LevelEventType.PARTICLES_SHOOT_SMOKE) { effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_SHOOT); } else { effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_SHOOT_WHITE_SMOKE); @@ -225,13 +225,13 @@ public class JavaLevelEventTranslator extends PacketTranslator { + case PARTICLES_DESTROY_BLOCK -> { effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_DESTROY_BLOCK); BreakBlockEventData breakBlockEventData = (BreakBlockEventData) packet.getData(); effectPacket.setData(session.getBlockMappings().getBedrockBlockId(breakBlockEventData.getBlockState())); } - case BREAK_SPLASH_POTION, BREAK_SPLASH_POTION2 -> { + case PARTICLES_SPELL_POTION_SPLASH, PARTICLES_INSTANT_POTION_SPLASH -> { effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_POTION_SPLASH); effectPacket.setPosition(pos.add(0, -0.5f, 0)); @@ -247,16 +247,16 @@ public class JavaLevelEventTranslator extends PacketTranslator effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_EYE_OF_ENDER_DEATH); - case MOB_SPAWN -> effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_MOB_BLOCK_SPAWN); // TODO: Check, but I don't think I really verified this ever went into effect on Java - case BONEMEAL_GROW_WITH_SOUND, BONEMEAL_GROW -> { - effectPacket.setType(levelEvent == LevelEventType.BONEMEAL_GROW ? org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_TURTLE_EGG : org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_CROP_GROWTH); + case PARTICLES_EYE_OF_ENDER_DEATH -> effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_EYE_OF_ENDER_DEATH); + case PARTICLES_MOBBLOCK_SPAWN -> effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_MOB_BLOCK_SPAWN); // TODO: Check, but I don't think I really verified this ever went into effect on Java + case PARTICLES_AND_SOUND_PLANT_GROWTH -> { + effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_CROP_GROWTH); BonemealGrowEventData growEventData = (BonemealGrowEventData) packet.getData(); effectPacket.setData(growEventData.getParticleCount()); } - case EGG_CRACK -> effectPacket.setType(ParticleType.VILLAGER_HAPPY); // both the lil green sparkle - case ENDERDRAGON_FIREBALL_EXPLODE -> { + case PARTICLES_EGG_CRACK -> effectPacket.setType(ParticleType.VILLAGER_HAPPY); // both the lil green sparkle + case PARTICLES_DRAGON_FIREBALL_SPLASH -> { effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_EYE_OF_ENDER_DEATH); // TODO DragonFireballEventData fireballEventData = (DragonFireballEventData) packet.getData(); @@ -271,15 +271,15 @@ public class JavaLevelEventTranslator extends PacketTranslator { + case PARTICLES_DRAGON_BLOCK_BREAK -> { effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_GENERIC_SPAWN); effectPacket.setData(61); } - case EVAPORATE -> { + case PARTICLES_WATER_EVAPORATING -> { effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_EVAPORATE_WATER); effectPacket.setPosition(pos.add(-0.5f, 0.5f, -0.5f)); } - case END_GATEWAY_SPAWN -> { + case ANIMATION_END_GATEWAY_SPAWN -> { effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_EXPLOSION); LevelSoundEventPacket soundEventPacket = new LevelSoundEventPacket(); @@ -292,11 +292,11 @@ public class JavaLevelEventTranslator extends PacketTranslator effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_DRIPSTONE_DRIP); - case ELECTRIC_SPARK -> effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_ELECTRIC_SPARK); // Matches with a Bedrock server but doesn't seem to match up with Java - case WAX_ON -> effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_WAX_ON); - case WAX_OFF -> effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_WAX_OFF); - case SCRAPE -> effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_SCRAPE); - case SCULK_BLOCK_CHARGE -> { + case PARTICLES_ELECTRIC_SPARK -> effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_ELECTRIC_SPARK); // Matches with a Bedrock server but doesn't seem to match up with Java + case PARTICLES_AND_SOUND_WAX_ON -> effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_WAX_ON); + case PARTICLES_WAX_OFF -> effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_WAX_OFF); + case PARTICLES_SCRAPE -> effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_SCRAPE); + case PARTICLES_SCULK_CHARGE -> { SculkBlockChargeEventData eventData = (SculkBlockChargeEventData) packet.getData(); LevelEventGenericPacket levelEventPacket = new LevelEventGenericPacket(); // TODO add SCULK_BLOCK_CHARGE sound @@ -324,7 +324,7 @@ public class JavaLevelEventTranslator extends PacketTranslator { + case PARTICLES_SCULK_SHRIEK -> { LevelEventGenericPacket levelEventPacket = new LevelEventGenericPacket(); levelEventPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_SCULK_SHRIEK); levelEventPacket.setTag( @@ -346,7 +346,7 @@ public class JavaLevelEventTranslator extends PacketTranslator { + case SOUND_STOP_JUKEBOX_SONG -> { String bedrockSound = session.getWorldCache().removeActiveRecord(origin); if (bedrockSound == null) { // Vanilla record diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings index 2ac0c1415..420cbe173 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 2ac0c1415cb9063c405dbd7e14f2d426a0ba1180 +Subproject commit 420cbe173ffa0667d4607715f9e3d43402e1ab77 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1456a7e34..23cd00a97 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ websocket = "1.5.1" protocol = "3.0.0.Beta2-20240616.144648-10" raknet = "1.0.0.CR3-20240416.144209-1" mcauthlib = "e5b0bcc" -mcprotocollib = "4f5f650" +mcprotocollib = "1.21-20240616.154144-5" 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.GeyserMC", name = "mcprotocollib", version.ref = "mcprotocollib" } +mcprotocollib = { group = "org.geysermc.mcprotocollib", name = "protocol", 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 63a3da7c564de2786cafedc60dd13e13d8ae6c92 Mon Sep 17 00:00:00 2001 From: Eclipse <116838833+eclipseisoffline@users.noreply.github.com> Date: Sun, 16 Jun 2024 23:35:18 +0000 Subject: [PATCH 110/233] Fix reading custom jukebox songs (#4757) * Read sound event objects properly in jukebox song * Add debug log for unexpected sound event type --- .../java/org/geysermc/geyser/level/JukeboxSong.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/level/JukeboxSong.java b/core/src/main/java/org/geysermc/geyser/level/JukeboxSong.java index fd6ce693d..156a62cd1 100644 --- a/core/src/main/java/org/geysermc/geyser/level/JukeboxSong.java +++ b/core/src/main/java/org/geysermc/geyser/level/JukeboxSong.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.level; import org.cloudburstmc.nbt.NbtMap; +import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; @@ -33,7 +34,16 @@ public record JukeboxSong(String soundEvent, String description) { public static JukeboxSong read(RegistryEntry entry) { NbtMap data = entry.getData(); - String soundEvent = data.getString("sound_event"); + Object soundEventObject = data.get("sound_event"); + String soundEvent; + if (soundEventObject instanceof NbtMap map) { + soundEvent = map.getString("sound_id"); + } else if (soundEventObject instanceof String string) { + soundEvent = string; + } else { + soundEvent = ""; + GeyserImpl.getInstance().getLogger().debug("Sound event for " + entry.getId() + " was of an unexpected type! Expected string or NBT map, got " + soundEventObject); + } String description = MessageTranslator.deserializeDescription(data); return new JukeboxSong(soundEvent, description); } From deb25d7147360285f2753825fb6f8765a406327c Mon Sep 17 00:00:00 2001 From: basaigh <53559772+basaigh@users.noreply.github.com> Date: Mon, 17 Jun 2024 13:17:57 +0100 Subject: [PATCH 111/233] Bump mappings to fix effects error on startup (#4760) --- 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 420cbe173..ff44a3257 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 420cbe173ffa0667d4607715f9e3d43402e1ab77 +Subproject commit ff44a32574d0cac242aa99d8f97af0b5c636c0cf From 29928c2d830838cba51a8ba1f6e2d11fff218cd9 Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 17 Jun 2024 18:46:57 +0200 Subject: [PATCH 112/233] Sanity check for shulker boxes (#4762) --- .../org/geysermc/geyser/level/block/type/BlockState.java | 9 +++++++++ .../block/entity/ShulkerBoxBlockEntityTranslator.java | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java index 36c31f32e..2a4b1774d 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java @@ -73,6 +73,15 @@ public final class BlockState { return (Boolean) value; } + public > T getValue(Property property, T def) { + var value = get(property); + if (value == null) { + return def; + } + //noinspection unchecked + return (T) value; + } + @Nullable private Comparable get(Property property) { Property[] keys = this.block.propertyKeys(); 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 e6d19e492..cac40b350 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 @@ -30,6 +30,7 @@ import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.level.block.type.BlockState; +import org.geysermc.geyser.level.physics.Direction; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.inventory.ShulkerInventoryTranslator; import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @@ -42,6 +43,6 @@ public class ShulkerBoxBlockEntityTranslator extends BlockEntityTranslator imple */ @Override public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, BlockState blockState) { - bedrockNbt.putByte("facing", (byte) blockState.getValue(Properties.FACING).ordinal()); + bedrockNbt.putByte("facing", (byte) blockState.getValue(Properties.FACING, Direction.UP).ordinal()); } } From 77fa37ff828cf31fc09710a5f4c9e57ab2c88944 Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 17 Jun 2024 21:31:54 +0200 Subject: [PATCH 113/233] Fix: readme not being synched to modrinth, publish spigot/bungee/velocity variants to modrinth (#4761) * Fix: readme not being synched to modrinth * use new build_number system env var * also upload bungee/spigot/velocity * change name * undo debug mode, oops --- .github/workflows/build.yml | 11 ++------ bootstrap/bungeecord/build.gradle.kts | 5 ++++ bootstrap/mod/build.gradle.kts | 7 +++++ bootstrap/mod/fabric/build.gradle.kts | 1 + bootstrap/mod/neoforge/build.gradle.kts | 1 + bootstrap/spigot/build.gradle.kts | 5 ++++ bootstrap/velocity/build.gradle.kts | 5 ++++ build-logic/build.gradle.kts | 3 +++ build-logic/src/main/kotlin/LibsAccessor.kt | 6 +++++ .../geyser.modded-conventions.gradle.kts | 27 +++++-------------- ....modrinth-uploading-conventions.gradle.kts | 18 +++++++++++++ build.gradle.kts | 14 ++++++++++ gradle/libs.versions.toml | 5 ++-- 13 files changed, 76 insertions(+), 32 deletions(-) create mode 100644 build-logic/src/main/kotlin/LibsAccessor.kt create mode 100644 build-logic/src/main/kotlin/geyser.modrinth-uploading-conventions.gradle.kts diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0e94ce965..ccc4dd79c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -103,19 +103,12 @@ jobs: bootstrap/viaproxy/build/libs/Geyser-ViaProxy.jar changelog: ${{ steps.metadata.outputs.body }} - - name: Publish to Modrinth (Fabric) + - name: Publish to Modrinth if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} env: BUILD_NUMBER: ${{ steps.release-info.outputs.curentRelease }} MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }} - run: ./gradlew fabric:modrinth - - - name: Publish to Modrinth (NeoForge) - if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} - env: - BUILD_NUMBER: ${{ steps.release-info.outputs.curentRelease }} - MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }} - run: ./gradlew neoforge:modrinth + run: ./gradlew modrinth - name: Notify Discord if: ${{ (success() || failure()) && github.repository == 'GeyserMC/Geyser' }} diff --git a/bootstrap/bungeecord/build.gradle.kts b/bootstrap/bungeecord/build.gradle.kts index e93c096a1..910e50723 100644 --- a/bootstrap/bungeecord/build.gradle.kts +++ b/bootstrap/bungeecord/build.gradle.kts @@ -34,3 +34,8 @@ tasks.withType { exclude(dependency("io.netty:netty-resolver-dns:.*")) } } + +modrinth { + uploadFile.set(tasks.getByPath("shadowJar")) + loaders.add("bungeecord") +} diff --git a/bootstrap/mod/build.gradle.kts b/bootstrap/mod/build.gradle.kts index 7651a2df2..32224d00b 100644 --- a/bootstrap/mod/build.gradle.kts +++ b/bootstrap/mod/build.gradle.kts @@ -6,6 +6,13 @@ loom { mixin.defaultRefmapName.set("geyser-refmap.json") } +afterEvaluate { + // We don't need these + tasks.named("remapModrinthJar").configure { + enabled = false + } +} + dependencies { api(projects.core) compileOnly(libs.mixin) diff --git a/bootstrap/mod/fabric/build.gradle.kts b/bootstrap/mod/fabric/build.gradle.kts index cd513c1e4..25bd0af9d 100644 --- a/bootstrap/mod/fabric/build.gradle.kts +++ b/bootstrap/mod/fabric/build.gradle.kts @@ -63,6 +63,7 @@ tasks { modrinth { loaders.add("fabric") + uploadFile.set(tasks.getByPath("remapModrinthJar")) dependencies { required.project("fabric-api") } diff --git a/bootstrap/mod/neoforge/build.gradle.kts b/bootstrap/mod/neoforge/build.gradle.kts index 92ffae7e5..e0e7c2dfa 100644 --- a/bootstrap/mod/neoforge/build.gradle.kts +++ b/bootstrap/mod/neoforge/build.gradle.kts @@ -55,4 +55,5 @@ tasks { modrinth { loaders.add("neoforge") + uploadFile.set(tasks.getByPath("remapModrinthJar")) } \ No newline at end of file diff --git a/bootstrap/spigot/build.gradle.kts b/bootstrap/spigot/build.gradle.kts index 7ccb50484..fcb85f100 100644 --- a/bootstrap/spigot/build.gradle.kts +++ b/bootstrap/spigot/build.gradle.kts @@ -76,3 +76,8 @@ tasks.withType { exclude(dependency("com.mojang:.*")) } } + +modrinth { + uploadFile.set(tasks.getByPath("shadowJar")) + loaders.addAll("spigot", "paper") +} diff --git a/bootstrap/velocity/build.gradle.kts b/bootstrap/velocity/build.gradle.kts index da826803c..4daad9784 100644 --- a/bootstrap/velocity/build.gradle.kts +++ b/bootstrap/velocity/build.gradle.kts @@ -69,4 +69,9 @@ tasks.withType { exclude(dependency("net.kyori:adventure-text-serializer-legacy:.*")) exclude(dependency("net.kyori:adventure-nbt:.*")) } +} + +modrinth { + uploadFile.set(tasks.getByPath("shadowJar")) + loaders.addAll("velocity") } \ No newline at end of file diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts index b7aab2bf0..190386667 100644 --- a/build-logic/build.gradle.kts +++ b/build-logic/build.gradle.kts @@ -12,6 +12,9 @@ repositories { } dependencies { + // this is OK as long as the same version catalog is used in the main build and build-logic + // see https://github.com/gradle/gradle/issues/15383#issuecomment-779893192 + implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location)) implementation(libs.indra) implementation(libs.shadow) implementation(libs.architectury.plugin) diff --git a/build-logic/src/main/kotlin/LibsAccessor.kt b/build-logic/src/main/kotlin/LibsAccessor.kt new file mode 100644 index 000000000..2a0c09eb6 --- /dev/null +++ b/build-logic/src/main/kotlin/LibsAccessor.kt @@ -0,0 +1,6 @@ +import org.gradle.accessors.dm.LibrariesForLibs +import org.gradle.api.Project +import org.gradle.kotlin.dsl.getByType + +val Project.libs: LibrariesForLibs + get() = rootProject.extensions.getByType() \ 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 86c2a2f6a..7952bcf14 100644 --- a/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts @@ -8,7 +8,6 @@ plugins { id("geyser.publish-conventions") id("architectury-plugin") id("dev.architectury.loom") - id("com.modrinth.minotaur") } // These are provided by Minecraft/modded platforms already, no need to include them @@ -39,7 +38,7 @@ provided("io.netty", "netty-resolver-dns-native-macos") provided("org.ow2.asm", "asm") architectury { - minecraft = "1.20.5" + minecraft = libs.minecraft.get().version as String } loom { @@ -83,7 +82,7 @@ tasks { register("remapModrinthJar", RemapJarTask::class) { dependsOn(shadowJar) inputFile.set(shadowJar.get().archiveFile) - archiveVersion.set(project.version.toString() + "+build." + System.getenv("GITHUB_RUN_NUMBER")) + archiveVersion.set(project.version.toString() + "+build." + System.getenv("BUILD_NUMBER")) archiveClassifier.set("") } } @@ -93,7 +92,7 @@ afterEvaluate { // These are shaded, no need to JiJ them configurations["shadow"].dependencies.forEach {shadowed -> - println("Not including shadowed dependency: ${shadowed.group}:${shadowed.name}") + //println("Not including shadowed dependency: ${shadowed.group}:${shadowed.name}") providedDependencies.add("${shadowed.group}:${shadowed.name}") } @@ -101,16 +100,16 @@ afterEvaluate { 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}") + //println("Including dependency via JiJ: ${dep.id}") dependencies.add("include", dep.moduleVersion.id.toString()) } else { - println("Not including ${dep.id} for ${project.name}!") + //println("Not including ${dep.id} for ${project.name}!") } } } dependencies { - minecraft("com.mojang:minecraft:1.21") + minecraft(libs.minecraft) mappings(loom.officialMojangMappings()) } @@ -121,18 +120,4 @@ repositories { 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") - versionNumber.set(project.version as String + "-" + System.getenv("GITHUB_RUN_NUMBER")) - versionType.set("beta") - changelog.set("A changelog can be found at https://github.com/GeyserMC/Geyser/commits") - - syncBodyFrom.set(rootProject.file("README.md").readText()) - - uploadFile.set(tasks.getByPath("remapModrinthJar")) - gameVersions.addAll("1.21") - failSilently.set(true) } \ No newline at end of file diff --git a/build-logic/src/main/kotlin/geyser.modrinth-uploading-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.modrinth-uploading-conventions.gradle.kts new file mode 100644 index 000000000..a4a8cd7d6 --- /dev/null +++ b/build-logic/src/main/kotlin/geyser.modrinth-uploading-conventions.gradle.kts @@ -0,0 +1,18 @@ +plugins { + id("com.modrinth.minotaur") +} + +// Ensure that the readme is synched +tasks.modrinth.get().dependsOn(tasks.modrinthSyncBody) + +modrinth { + token.set(System.getenv("MODRINTH_TOKEN") ?: "") // Even though this is the default value, apparently this prevents GitHub Actions caching the token? + projectId.set("geyser") + versionNumber.set(project.version as String + "-" + System.getenv("BUILD_NUMBER")) + versionType.set("beta") + changelog.set("A changelog can be found at https://github.com/GeyserMC/Geyser/commits") + gameVersions.add(libs.minecraft.get().version as String) + failSilently.set(true) + + syncBodyFrom.set(rootProject.file("README.md").readText()) +} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index dfdff2187..dfbf9837f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -26,6 +26,14 @@ val moddedPlatforms = setOf( projects.mod ).map { it.dependencyProject } +val modrinthPlatforms = setOf( + projects.bungeecord, + projects.fabric, + projects.neoforge, + projects.spigot, + projects.velocity +).map { it.dependencyProject } + subprojects { apply { plugin("java-library") @@ -38,4 +46,10 @@ subprojects { in moddedPlatforms -> plugins.apply("geyser.modded-conventions") else -> plugins.apply("geyser.base-conventions") } + + // Not combined with platform-conventions as that also contains + // platforms which we cant publish to modrinth + if (modrinthPlatforms.contains(this)) { + plugins.apply("geyser.modrinth-uploading-conventions") + } } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 23cd00a97..784f30053 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -28,12 +28,12 @@ commodore = "2.2" bungeecord = "a7c6ede" velocity = "3.3.0-SNAPSHOT" viaproxy = "3.2.1" -fabric-minecraft = "1.21" fabric-loader = "0.15.11" fabric-api = "0.100.1+1.21" fabric-permissions = "0.2-SNAPSHOT" neoforge-minecraft = "21.0.0-beta" mixin = "0.8.5" +minecraft = "1.21" # plugin versions indra = "3.1.3" @@ -90,8 +90,9 @@ paper-mojangapi = { group = "io.papermc.paper", name = "paper-mojangapi", versio mixin = { group = "org.spongepowered", name = "mixin", version.ref = "mixin" } +minecraft = { group = "com.mojang", name = "minecraft", version.ref = "minecraft" } + # 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" } From a9300fb1ab0a0cf281be6a777eeab16354520f95 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 18 Jun 2024 15:30:19 -0400 Subject: [PATCH 114/233] Vault: show some components in block entity (enchantments, potion types) --- .../geyser/inventory/item/Potion.java | 9 +++ .../translator/item/ItemTranslator.java | 2 +- .../entity/VaultBlockEntityTranslator.java | 57 ++++++++++++++++++- 3 files changed, 64 insertions(+), 4 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 c4d20c623..129c365a9 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 @@ -102,6 +102,15 @@ public enum Potion { return new PotionContents(this.ordinal(), -1, Collections.emptyList()); } + public static Potion getByJavaIdentifier(String javaIdentifier) { + for (Potion potion : VALUES) { + if (potion.javaIdentifier.equals(javaIdentifier)) { + return potion; + } + } + return null; + } + public static @Nullable Potion getByJavaId(int javaId) { if (javaId >= 0 && javaId < VALUES.length) { return VALUES[javaId]; 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 7572f5e61..a8d29c465 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 @@ -135,7 +135,7 @@ public final class ItemTranslator { .build(); } - private static ItemData.@NonNull Builder translateToBedrock(GeyserSession session, Item javaItem, ItemMapping bedrockItem, int count, @Nullable DataComponents components) { + public static ItemData.@NonNull Builder translateToBedrock(GeyserSession session, Item javaItem, ItemMapping bedrockItem, int count, @Nullable DataComponents components) { BedrockItemBuilder nbtBuilder = new BedrockItemBuilder(); boolean hideTooltips = false; diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/VaultBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/VaultBlockEntityTranslator.java index 50fd64202..81be5b33a 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/VaultBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/VaultBlockEntityTranslator.java @@ -25,20 +25,32 @@ package org.geysermc.geyser.translator.level.block.entity; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.longs.LongArrayList; import it.unimi.dsi.fastutil.longs.LongList; 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.cloudburstmc.protocol.common.util.TriConsumer; import org.geysermc.geyser.entity.type.player.PlayerEntity; +import org.geysermc.geyser.inventory.item.Potion; +import org.geysermc.geyser.item.enchantment.Enchantment; import org.geysermc.geyser.level.block.type.BlockState; 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.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemEnchantments; import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; @BlockEntity(type = BlockEntityType.VAULT) @@ -67,9 +79,25 @@ public class VaultBlockEntityTranslator extends BlockEntityTranslator { .putByte("WasPickedUp", (byte) 0).build()); } else { int count = item.getInt("count"); - NbtMapBuilder bedrockItem = BedrockItemBuilder.createItemNbt(mapping, count, mapping.getBedrockData()); - // TODO handle components... - bedrockNbt.putCompound("display_item", bedrockItem.build()); + NbtMap componentsTag = item.getCompound("components"); + NbtMapBuilder itemAsNbt; + if (!componentsTag.isEmpty()) { + DataComponents components = new DataComponents(new HashMap<>()); + for (Map.Entry entry : componentsTag.entrySet()) { + var consumer = DATA_COMPONENT_DECODERS.get(entry.getKey()); + if (consumer != null) { + consumer.accept(session, (NbtMap) entry.getValue(), components); + } + } + ItemData bedrockItem = ItemTranslator.translateToBedrock(session, mapping.getJavaItem(), mapping, count, components).build(); + itemAsNbt = BedrockItemBuilder.createItemNbt(mapping, bedrockItem.getCount(), bedrockItem.getDamage()); + if (bedrockItem.getTag() != null) { + itemAsNbt.putCompound("tag", bedrockItem.getTag()); + } + } else { + itemAsNbt = BedrockItemBuilder.createItemNbt(mapping, count, mapping.getBedrockData()); + } + bedrockNbt.putCompound("display_item", itemAsNbt.build()); } List connectedPlayers = sharedData.getList("connected_players", NbtType.INT_ARRAY); @@ -96,4 +124,27 @@ public class VaultBlockEntityTranslator extends BlockEntityTranslator { private static UUID uuidFromIntArray(int[] parts) { return new UUID((long) parts[0] << 32 | (parts[1] & 0xFFFFFFFFL), (long) parts[2] << 32 | (parts[3] & 0xFFFFFFFFL)); } + + // This might be easier to maintain in the long run so items don't have two translate methods. + // Also, it's not out of the question that block entities get the data component treatment, likely rendering this useless. + // The goal is to just translate the basics so clients know what potion is roughly present, and that any enchantment even exists. + private static final Map> DATA_COMPONENT_DECODERS = Map.of( + "minecraft:potion_contents", (session, tag, components) -> { + String potionId = tag.getString("potion"); + Potion potion = Potion.getByJavaIdentifier(potionId); + components.put(DataComponentType.POTION_CONTENTS, potion.toComponent()); + }, + "minecraft:enchantments", (session, tag, components) -> { // Enchanted books already have glint. Translating them doesn't matter. + NbtMap levels = tag.getCompound("levels"); + List enchantmentRegistry = session.getRegistryCache().enchantments().values(); + Int2ObjectMap enchantments = new Int2ObjectOpenHashMap<>(levels.size()); + for (Map.Entry entry : levels.entrySet()) { + for (int i = 0; i < enchantmentRegistry.size(); i++) { + if (enchantmentRegistry.get(i).identifier().equals(entry.getKey())) { + enchantments.put(i, (Integer) entry.getValue()); + } + } + } + components.put(DataComponentType.ENCHANTMENTS, new ItemEnchantments(enchantments, true)); + }); } From 6884a0f7db8a0edd078f1367cda0600402aac198 Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 19 Jun 2024 02:37:34 +0200 Subject: [PATCH 115/233] Fix: norwegian locale handling (#4716) --- .../main/java/org/geysermc/geyser/text/GeyserLocale.java | 7 +++++++ 1 file changed, 7 insertions(+) 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 cfe950409..28fd6f9a4 100644 --- a/core/src/main/java/org/geysermc/geyser/text/GeyserLocale.java +++ b/core/src/main/java/org/geysermc/geyser/text/GeyserLocale.java @@ -259,6 +259,13 @@ public class GeyserLocale { // Invalid locale return locale; } + + // See https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes - covers the special case that is norwegian + String lowerCaseLocale = locale.toLowerCase(Locale.ROOT); + if (lowerCaseLocale.equals("nn_no") || lowerCaseLocale.equals("no_no")) { + locale = "nb_NO"; + } + String language = locale.substring(0, 2); String country = locale.substring(3); return language.toLowerCase(Locale.ENGLISH) + "_" + country.toUpperCase(Locale.ENGLISH); From 2c47330509bfa11101786a29046b0e3c26f9fd03 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Wed, 19 Jun 2024 15:52:54 -0400 Subject: [PATCH 116/233] Use integrated world managers for decorated pot animation --- .../mod/world/GeyserModWorldManager.java | 25 +++++++++++++++++++ .../manager/GeyserSpigotWorldManager.java | 20 +++++++++++++++ .../geysermc/geyser/level/WorldManager.java | 9 +++++++ .../java/level/JavaBlockEventTranslator.java | 21 ++++++++++++++++ 4 files changed, 75 insertions(+) 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 ef8c3ec0a..db1768737 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 @@ -30,6 +30,7 @@ import net.minecraft.SharedConstants; import net.minecraft.core.BlockPos; import net.minecraft.core.RegistryAccess; import net.minecraft.core.component.DataComponents; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; @@ -39,10 +40,12 @@ 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.DecoratedPotBlockEntity; import net.minecraft.world.level.chunk.ChunkAccess; 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.geysermc.geyser.level.GeyserWorldManager; import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.platform.mod.GeyserModBootstrap; @@ -56,6 +59,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponen import java.util.HashMap; import java.util.List; import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; public class GeyserModWorldManager extends GeyserWorldManager { @@ -161,6 +165,27 @@ public class GeyserModWorldManager extends GeyserWorldManager { return future; } + @Override + public void getDecoratedPotData(GeyserSession session, Vector3i pos, Consumer> apply) { + server.execute(() -> { + ServerPlayer player = getPlayer(session); + if (player == null) { + return; + } + + BlockPos blockPos = new BlockPos(pos.getX(), pos.getY(), pos.getZ()); + // Don't create a new block entity if invalid + //noinspection resource - level() is just a getter + BlockEntity blockEntity = player.level().getChunkAt(blockPos).getBlockEntity(blockPos); + if (blockEntity instanceof DecoratedPotBlockEntity pot) { + List sherds = pot.getDecorations().ordered() + .stream().map(item -> BuiltInRegistries.ITEM.getKey(item).toString()) + .toList(); + apply.accept(sherds); + } + }); + } + private ServerPlayer getPlayer(GeyserSession session) { return server.getPlayerList().getPlayer(session.getPlayerEntity().getUuid()); } 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 e247a72c7..73356c4e7 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 @@ -29,10 +29,13 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.block.Block; +import org.bukkit.block.DecoratedPot; 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.math.vector.Vector3i; +import org.geysermc.erosion.bukkit.BukkitUtils; import org.geysermc.erosion.bukkit.PickBlockUtils; import org.geysermc.erosion.bukkit.SchedulerUtils; import org.geysermc.geyser.GeyserImpl; @@ -43,8 +46,10 @@ 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 java.util.List; import java.util.Objects; import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; /** * The base world manager to use when there is no supported NMS revision @@ -146,6 +151,21 @@ public class GeyserSpigotWorldManager extends WorldManager { return future.thenApply(RAW_TRANSFORMER); } + public void getDecoratedPotData(GeyserSession session, Vector3i pos, Consumer> apply) { + Player bukkitPlayer; + if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUuid())) == null) { + return; + } + Block block = bukkitPlayer.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); + SchedulerUtils.runTask(this.plugin, () -> { + var state = BukkitUtils.getBlockState(block); + if (!(state instanceof DecoratedPot pot)) { + return; + } + apply.accept(pot.getShards().stream().map(material -> material.getKey().toString()).toList()); + }, block); + } + /** * This should be set to true if we are post-1.13 but before the latest version, and we should convert the old block state id * to the current one. 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 3670b6b73..4a20771f2 100644 --- a/core/src/main/java/org/geysermc/geyser/level/WorldManager.java +++ b/core/src/main/java/org/geysermc/geyser/level/WorldManager.java @@ -43,9 +43,11 @@ import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemCodecHel import org.geysermc.mcprotocollib.protocol.data.game.setting.Difficulty; import java.util.HashMap; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; import java.util.function.Function; /** @@ -209,6 +211,13 @@ public abstract class WorldManager { return CompletableFuture.completedFuture(null); } + /** + * Retrieves decorated pot sherds from the server. Used to ensure the data is not erased on animation sent + * through the BlockEntityDataPacket. + */ + public void getDecoratedPotData(GeyserSession session, Vector3i pos, Consumer> apply) { + } + protected static final Function, DataComponents> RAW_TRANSFORMER = map -> { try { Map, DataComponent> components = new HashMap<>(); 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 d6e45adc3..f56750d12 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 @@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.protocol.java.level; import it.unimi.dsi.fastutil.objects.Object2ObjectMaps; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMapBuilder; +import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket; import org.cloudburstmc.protocol.bedrock.packet.BlockEventPacket; import org.geysermc.geyser.api.util.PlatformType; @@ -126,6 +127,26 @@ public class JavaBlockEventTranslator extends PacketTranslator { + BlockEntityDataPacket blockEntityPacket = new BlockEntityDataPacket(); + blockEntityPacket.setBlockPosition(position); + + NbtMapBuilder builder = BlockEntityTranslator.getConstantBedrockTag("DecoratedPot", position); + builder.putList("sherds", NbtType.STRING, sherds); + builder.putByte("animation", switch (potValue.getWobbleStyle()) { + case POSITIVE -> (byte) 2; + case NEGATIVE -> (byte) 1; + }); + + blockEntityPacket.setData(builder.build()); + session.sendUpstreamPacket(blockEntityPacket); + }); + } else if (session.getGeyser().getLogger().isDebug()) { + session.getGeyser().getLogger().debug("Unhandled block event packet: " + packet); } } } From 34158f946331b5c1c3db13d64e33dcae10c34a63 Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 19 Jun 2024 22:27:14 +0200 Subject: [PATCH 117/233] Feat: Add changelog to modrinth releases (#4770) * Feat: Add changelog to modrinth releases * oops --- .github/workflows/build.yml | 1 + .../kotlin/geyser.modrinth-uploading-conventions.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ccc4dd79c..2bcf25e8e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -106,6 +106,7 @@ jobs: - name: Publish to Modrinth if: ${{ success() && github.repository == 'GeyserMC/Geyser' && github.ref_name == 'master' }} env: + CHANGELOG: ${{ steps.metadata.outputs.body }} BUILD_NUMBER: ${{ steps.release-info.outputs.curentRelease }} MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }} run: ./gradlew modrinth diff --git a/build-logic/src/main/kotlin/geyser.modrinth-uploading-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.modrinth-uploading-conventions.gradle.kts index a4a8cd7d6..d710ae1a2 100644 --- a/build-logic/src/main/kotlin/geyser.modrinth-uploading-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.modrinth-uploading-conventions.gradle.kts @@ -10,7 +10,7 @@ modrinth { projectId.set("geyser") versionNumber.set(project.version as String + "-" + System.getenv("BUILD_NUMBER")) versionType.set("beta") - changelog.set("A changelog can be found at https://github.com/GeyserMC/Geyser/commits") + changelog.set(System.getenv("CHANGELOG") ?: "") gameVersions.add(libs.minecraft.get().version as String) failSilently.set(true) From 126d56d144db6e105f9de49a8fbe384e320b18de Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 19 Jun 2024 23:48:55 +0200 Subject: [PATCH 118/233] Fix: Ignore invalid block entity data sent by Java server (#4766) * Proper block entity checks; ignore invalid block entity data sent by Java server * fix intelliJ warning about potentially null block state * Use auto-generated block entity types instead of hardcoding them * undo some diff * Update BlockRegistryPopulator.java * Access block entity type of state by getting the block first * deprecate JavaBlockState#hasBlockEntity * Simplify check * Add type check in JavaBlockEntityDataTranslator, ensure deprecated setBlockEntity() method still sets piston behavior * nullability annotations * yeet duplicate check --- .../custom/nonvanilla/JavaBlockState.java | 8 + .../geysermc/geyser/level/block/Blocks.java | 333 +++++++++--------- .../level/block/GeyserJavaBlockState.java | 12 +- .../geyser/level/block/type/Block.java | 19 +- .../geyser/level/block/type/BlockState.java | 8 - .../populator/BlockRegistryPopulator.java | 3 - .../BrushableBlockEntityTranslator.java | 1 - .../DecoratedPotBlockEntityTranslator.java | 1 - .../DoubleChestBlockEntityTranslator.java | 5 - .../ShulkerBoxBlockEntityTranslator.java | 3 +- .../entity/SkullBlockEntityTranslator.java | 1 - .../entity/SpawnerBlockEntityTranslator.java | 1 - .../StructureBlockBlockEntityTranslator.java | 1 - .../TrialSpawnerBlockEntityTranslator.java | 1 - .../level/JavaBlockEntityDataTranslator.java | 12 +- .../JavaLevelChunkWithLightTranslator.java | 40 ++- 16 files changed, 225 insertions(+), 224 deletions(-) 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 f7da4b932..0dd0d3b33 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 @@ -73,7 +73,10 @@ public interface JavaBlockState { * Gets whether the block state has block entity * * @return whether the block state has block entity + * @deprecated Does not have an effect. If you were using this to + * set piston behavior, use {@link #pistonBehavior()} instead. */ + @Deprecated(forRemoval = true) boolean hasBlockEntity(); /** @@ -104,6 +107,11 @@ public interface JavaBlockState { Builder pistonBehavior(@Nullable String pistonBehavior); + /** + * @deprecated Does not have an effect. If you were using this to + * * set piston behavior, use {@link #pistonBehavior(String)} instead. + */ + @Deprecated(forRemoval = true) Builder hasBlockEntity(boolean hasBlockEntity); JavaBlockState build(); diff --git a/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java index 857a3fc13..735c1f6c4 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/Blocks.java @@ -33,6 +33,7 @@ import org.geysermc.geyser.level.physics.Axis; import org.geysermc.geyser.level.physics.Direction; import org.geysermc.geyser.level.physics.PistonBehavior; import org.geysermc.geyser.registry.BlockRegistries; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; import static org.geysermc.geyser.level.block.property.Properties.*; import static org.geysermc.geyser.level.block.type.Block.builder; @@ -89,11 +90,11 @@ public final class Blocks { public static final Block LAVA = register(new Block("lava", builder().destroyTime(100.0f).pushReaction(PistonBehavior.DESTROY) .intState(LEVEL))); public static final Block SAND = register(new Block("sand", builder().destroyTime(0.5f))); - public static final Block SUSPICIOUS_SAND = register(new Block("suspicious_sand", builder().setBlockEntity().destroyTime(0.25f).pushReaction(PistonBehavior.DESTROY) + public static final Block SUSPICIOUS_SAND = register(new Block("suspicious_sand", builder().setBlockEntity(BlockEntityType.BRUSHABLE_BLOCK).destroyTime(0.25f).pushReaction(PistonBehavior.DESTROY) .intState(DUSTED))); public static final Block RED_SAND = register(new Block("red_sand", builder().destroyTime(0.5f))); public static final Block GRAVEL = register(new Block("gravel", builder().destroyTime(0.6f))); - public static final Block SUSPICIOUS_GRAVEL = register(new Block("suspicious_gravel", builder().setBlockEntity().destroyTime(0.25f).pushReaction(PistonBehavior.DESTROY) + public static final Block SUSPICIOUS_GRAVEL = register(new Block("suspicious_gravel", builder().setBlockEntity(BlockEntityType.BRUSHABLE_BLOCK).destroyTime(0.25f).pushReaction(PistonBehavior.DESTROY) .intState(DUSTED))); public static final Block GOLD_ORE = register(new Block("gold_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); public static final Block DEEPSLATE_GOLD_ORE = register(new Block("deepslate_gold_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f))); @@ -220,7 +221,7 @@ public final class Blocks { public static final Block LAPIS_ORE = register(new Block("lapis_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); public static final Block DEEPSLATE_LAPIS_ORE = register(new Block("deepslate_lapis_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f))); public static final Block LAPIS_BLOCK = register(new Block("lapis_block", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); - public static final Block DISPENSER = register(new Block("dispenser", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(3.5f) + public static final Block DISPENSER = register(new Block("dispenser", builder().setBlockEntity(BlockEntityType.DISPENSER).requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .booleanState(TRIGGERED))); public static final Block SANDSTONE = register(new Block("sandstone", builder().requiresCorrectToolForDrops().destroyTime(0.8f))); @@ -230,67 +231,67 @@ public final class Blocks { .enumState(NOTEBLOCK_INSTRUMENT) .intState(NOTE) .booleanState(POWERED))); - public static final Block WHITE_BED = register(new BedBlock("white_bed", 0, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) + public static final Block WHITE_BED = register(new BedBlock("white_bed", 0, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART))); - public static final Block ORANGE_BED = register(new BedBlock("orange_bed", 1, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) + public static final Block ORANGE_BED = register(new BedBlock("orange_bed", 1, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART))); - public static final Block MAGENTA_BED = register(new BedBlock("magenta_bed", 2, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) + public static final Block MAGENTA_BED = register(new BedBlock("magenta_bed", 2, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART))); - public static final Block LIGHT_BLUE_BED = register(new BedBlock("light_blue_bed", 3, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) + public static final Block LIGHT_BLUE_BED = register(new BedBlock("light_blue_bed", 3, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART))); - public static final Block YELLOW_BED = register(new BedBlock("yellow_bed", 4, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) + public static final Block YELLOW_BED = register(new BedBlock("yellow_bed", 4, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART))); - public static final Block LIME_BED = register(new BedBlock("lime_bed", 5, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) + public static final Block LIME_BED = register(new BedBlock("lime_bed", 5, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART))); - public static final Block PINK_BED = register(new BedBlock("pink_bed", 6, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) + public static final Block PINK_BED = register(new BedBlock("pink_bed", 6, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART))); - public static final Block GRAY_BED = register(new BedBlock("gray_bed", 7, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) + public static final Block GRAY_BED = register(new BedBlock("gray_bed", 7, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART))); - public static final Block LIGHT_GRAY_BED = register(new BedBlock("light_gray_bed", 8, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) + public static final Block LIGHT_GRAY_BED = register(new BedBlock("light_gray_bed", 8, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART))); - public static final Block CYAN_BED = register(new BedBlock("cyan_bed", 9, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) + public static final Block CYAN_BED = register(new BedBlock("cyan_bed", 9, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART))); - public static final Block PURPLE_BED = register(new BedBlock("purple_bed", 10, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) + public static final Block PURPLE_BED = register(new BedBlock("purple_bed", 10, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART))); - public static final Block BLUE_BED = register(new BedBlock("blue_bed", 11, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) + public static final Block BLUE_BED = register(new BedBlock("blue_bed", 11, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART))); - public static final Block BROWN_BED = register(new BedBlock("brown_bed", 12, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) + public static final Block BROWN_BED = register(new BedBlock("brown_bed", 12, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART))); - public static final Block GREEN_BED = register(new BedBlock("green_bed", 13, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) + public static final Block GREEN_BED = register(new BedBlock("green_bed", 13, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART))); - public static final Block RED_BED = register(new BedBlock("red_bed", 14, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) + public static final Block RED_BED = register(new BedBlock("red_bed", 14, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART))); - public static final Block BLACK_BED = register(new BedBlock("black_bed", 15, builder().setBlockEntity().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) + public static final Block BLACK_BED = register(new BedBlock("black_bed", 15, builder().setBlockEntity(BlockEntityType.BED).destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OCCUPIED) .enumState(BED_PART))); @@ -335,7 +336,7 @@ public final class Blocks { public static final Block GREEN_WOOL = register(new Block("green_wool", builder().destroyTime(0.8f))); public static final Block RED_WOOL = register(new Block("red_wool", builder().destroyTime(0.8f))); public static final Block BLACK_WOOL = register(new Block("black_wool", builder().destroyTime(0.8f))); - public static final Block MOVING_PISTON = register(new MovingPistonBlock("moving_piston", builder().setBlockEntity().destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK) + public static final Block MOVING_PISTON = register(new MovingPistonBlock("moving_piston", builder().setBlockEntity(BlockEntityType.PISTON).destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .enumState(PISTON_TYPE))); public static final Block DANDELION = register(new Block("dandelion", builder().pushReaction(PistonBehavior.DESTROY))); @@ -360,7 +361,7 @@ public final class Blocks { public static final Block TNT = register(new Block("tnt", builder() .booleanState(UNSTABLE))); public static final Block BOOKSHELF = register(new Block("bookshelf", builder().destroyTime(1.5f))); - public static final Block CHISELED_BOOKSHELF = register(new Block("chiseled_bookshelf", builder().setBlockEntity().destroyTime(1.5f) + public static final Block CHISELED_BOOKSHELF = register(new Block("chiseled_bookshelf", builder().setBlockEntity(BlockEntityType.CHISELED_BOOKSHELF).destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(CHISELED_BOOKSHELF_SLOT_0_OCCUPIED) .booleanState(CHISELED_BOOKSHELF_SLOT_1_OCCUPIED) @@ -381,13 +382,13 @@ public final class Blocks { .booleanState(UP) .booleanState(WEST))); public static final Block SOUL_FIRE = register(new Block("soul_fire", builder().pushReaction(PistonBehavior.DESTROY))); - public static final Block SPAWNER = register(new SpawnerBlock("spawner", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(5.0f))); + public static final Block SPAWNER = register(new SpawnerBlock("spawner", builder().setBlockEntity(BlockEntityType.MOB_SPAWNER).requiresCorrectToolForDrops().destroyTime(5.0f))); public static final Block OAK_STAIRS = register(new Block("oak_stairs", builder().destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HALF) .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); - public static final Block CHEST = register(new ChestBlock("chest", builder().setBlockEntity().destroyTime(2.5f) + public static final Block CHEST = register(new ChestBlock("chest", builder().setBlockEntity(BlockEntityType.CHEST).destroyTime(2.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(CHEST_TYPE, ChestType.VALUES) .booleanState(WATERLOGGED))); @@ -405,34 +406,34 @@ public final class Blocks { .intState(AGE_7))); public static final Block FARMLAND = register(new Block("farmland", builder().destroyTime(0.6f) .intState(MOISTURE))); - public static final Block FURNACE = register(new FurnaceBlock("furnace", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(3.5f) + public static final Block FURNACE = register(new FurnaceBlock("furnace", builder().setBlockEntity(BlockEntityType.FURNACE).requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(LIT))); - public static final Block OAK_SIGN = register(new Block("oak_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block OAK_SIGN = register(new Block("oak_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f) .intState(ROTATION_16) .booleanState(WATERLOGGED))); - public static final Block SPRUCE_SIGN = register(new Block("spruce_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block SPRUCE_SIGN = register(new Block("spruce_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f) .intState(ROTATION_16) .booleanState(WATERLOGGED))); - public static final Block BIRCH_SIGN = register(new Block("birch_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block BIRCH_SIGN = register(new Block("birch_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f) .intState(ROTATION_16) .booleanState(WATERLOGGED))); - public static final Block ACACIA_SIGN = register(new Block("acacia_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block ACACIA_SIGN = register(new Block("acacia_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f) .intState(ROTATION_16) .booleanState(WATERLOGGED))); - public static final Block CHERRY_SIGN = register(new Block("cherry_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block CHERRY_SIGN = register(new Block("cherry_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f) .intState(ROTATION_16) .booleanState(WATERLOGGED))); - public static final Block JUNGLE_SIGN = register(new Block("jungle_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block JUNGLE_SIGN = register(new Block("jungle_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f) .intState(ROTATION_16) .booleanState(WATERLOGGED))); - public static final Block DARK_OAK_SIGN = register(new Block("dark_oak_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block DARK_OAK_SIGN = register(new Block("dark_oak_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f) .intState(ROTATION_16) .booleanState(WATERLOGGED))); - public static final Block MANGROVE_SIGN = register(new Block("mangrove_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block MANGROVE_SIGN = register(new Block("mangrove_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f) .intState(ROTATION_16) .booleanState(WATERLOGGED))); - public static final Block BAMBOO_SIGN = register(new Block("bamboo_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block BAMBOO_SIGN = register(new Block("bamboo_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f) .intState(ROTATION_16) .booleanState(WATERLOGGED))); public static final Block OAK_DOOR = register(new DoorBlock("oak_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) @@ -452,108 +453,108 @@ public final class Blocks { .enumState(HALF) .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); - public static final Block OAK_WALL_SIGN = register(new Block("oak_wall_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block OAK_WALL_SIGN = register(new Block("oak_wall_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block SPRUCE_WALL_SIGN = register(new Block("spruce_wall_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block SPRUCE_WALL_SIGN = register(new Block("spruce_wall_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block BIRCH_WALL_SIGN = register(new Block("birch_wall_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block BIRCH_WALL_SIGN = register(new Block("birch_wall_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block ACACIA_WALL_SIGN = register(new Block("acacia_wall_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block ACACIA_WALL_SIGN = register(new Block("acacia_wall_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block CHERRY_WALL_SIGN = register(new Block("cherry_wall_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block CHERRY_WALL_SIGN = register(new Block("cherry_wall_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block JUNGLE_WALL_SIGN = register(new Block("jungle_wall_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block JUNGLE_WALL_SIGN = register(new Block("jungle_wall_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block DARK_OAK_WALL_SIGN = register(new Block("dark_oak_wall_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block DARK_OAK_WALL_SIGN = register(new Block("dark_oak_wall_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block MANGROVE_WALL_SIGN = register(new Block("mangrove_wall_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block MANGROVE_WALL_SIGN = register(new Block("mangrove_wall_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block BAMBOO_WALL_SIGN = register(new Block("bamboo_wall_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block BAMBOO_WALL_SIGN = register(new Block("bamboo_wall_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block OAK_HANGING_SIGN = register(new Block("oak_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block OAK_HANGING_SIGN = register(new Block("oak_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f) .booleanState(ATTACHED) .intState(ROTATION_16) .booleanState(WATERLOGGED))); - public static final Block SPRUCE_HANGING_SIGN = register(new Block("spruce_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block SPRUCE_HANGING_SIGN = register(new Block("spruce_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f) .booleanState(ATTACHED) .intState(ROTATION_16) .booleanState(WATERLOGGED))); - public static final Block BIRCH_HANGING_SIGN = register(new Block("birch_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block BIRCH_HANGING_SIGN = register(new Block("birch_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f) .booleanState(ATTACHED) .intState(ROTATION_16) .booleanState(WATERLOGGED))); - public static final Block ACACIA_HANGING_SIGN = register(new Block("acacia_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block ACACIA_HANGING_SIGN = register(new Block("acacia_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f) .booleanState(ATTACHED) .intState(ROTATION_16) .booleanState(WATERLOGGED))); - public static final Block CHERRY_HANGING_SIGN = register(new Block("cherry_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block CHERRY_HANGING_SIGN = register(new Block("cherry_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f) .booleanState(ATTACHED) .intState(ROTATION_16) .booleanState(WATERLOGGED))); - public static final Block JUNGLE_HANGING_SIGN = register(new Block("jungle_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block JUNGLE_HANGING_SIGN = register(new Block("jungle_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f) .booleanState(ATTACHED) .intState(ROTATION_16) .booleanState(WATERLOGGED))); - public static final Block DARK_OAK_HANGING_SIGN = register(new Block("dark_oak_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block DARK_OAK_HANGING_SIGN = register(new Block("dark_oak_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f) .booleanState(ATTACHED) .intState(ROTATION_16) .booleanState(WATERLOGGED))); - public static final Block CRIMSON_HANGING_SIGN = register(new Block("crimson_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block CRIMSON_HANGING_SIGN = register(new Block("crimson_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f) .booleanState(ATTACHED) .intState(ROTATION_16) .booleanState(WATERLOGGED))); - public static final Block WARPED_HANGING_SIGN = register(new Block("warped_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block WARPED_HANGING_SIGN = register(new Block("warped_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f) .booleanState(ATTACHED) .intState(ROTATION_16) .booleanState(WATERLOGGED))); - public static final Block MANGROVE_HANGING_SIGN = register(new Block("mangrove_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block MANGROVE_HANGING_SIGN = register(new Block("mangrove_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f) .booleanState(ATTACHED) .intState(ROTATION_16) .booleanState(WATERLOGGED))); - public static final Block BAMBOO_HANGING_SIGN = register(new Block("bamboo_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block BAMBOO_HANGING_SIGN = register(new Block("bamboo_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f) .booleanState(ATTACHED) .intState(ROTATION_16) .booleanState(WATERLOGGED))); - public static final Block OAK_WALL_HANGING_SIGN = register(new Block("oak_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block OAK_WALL_HANGING_SIGN = register(new Block("oak_wall_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block SPRUCE_WALL_HANGING_SIGN = register(new Block("spruce_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block SPRUCE_WALL_HANGING_SIGN = register(new Block("spruce_wall_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block BIRCH_WALL_HANGING_SIGN = register(new Block("birch_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block BIRCH_WALL_HANGING_SIGN = register(new Block("birch_wall_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block ACACIA_WALL_HANGING_SIGN = register(new Block("acacia_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block ACACIA_WALL_HANGING_SIGN = register(new Block("acacia_wall_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block CHERRY_WALL_HANGING_SIGN = register(new Block("cherry_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block CHERRY_WALL_HANGING_SIGN = register(new Block("cherry_wall_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block JUNGLE_WALL_HANGING_SIGN = register(new Block("jungle_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block JUNGLE_WALL_HANGING_SIGN = register(new Block("jungle_wall_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block DARK_OAK_WALL_HANGING_SIGN = register(new Block("dark_oak_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block DARK_OAK_WALL_HANGING_SIGN = register(new Block("dark_oak_wall_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block MANGROVE_WALL_HANGING_SIGN = register(new Block("mangrove_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block MANGROVE_WALL_HANGING_SIGN = register(new Block("mangrove_wall_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block CRIMSON_WALL_HANGING_SIGN = register(new Block("crimson_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block CRIMSON_WALL_HANGING_SIGN = register(new Block("crimson_wall_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block WARPED_WALL_HANGING_SIGN = register(new Block("warped_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block WARPED_WALL_HANGING_SIGN = register(new Block("warped_wall_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block BAMBOO_WALL_HANGING_SIGN = register(new Block("bamboo_wall_hanging_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block BAMBOO_WALL_HANGING_SIGN = register(new Block("bamboo_wall_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); public static final Block LEVER = register(new Block("lever", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) @@ -608,7 +609,7 @@ public final class Blocks { public static final Block CLAY = register(new Block("clay", builder().destroyTime(0.6f))); public static final Block SUGAR_CANE = register(new Block("sugar_cane", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_15))); - public static final Block JUKEBOX = register(new Block("jukebox", builder().setBlockEntity().destroyTime(2.0f) + public static final Block JUKEBOX = register(new Block("jukebox", builder().setBlockEntity(BlockEntityType.JUKEBOX).destroyTime(2.0f) .booleanState(HAS_RECORD))); public static final Block OAK_FENCE = register(new Block("oak_fence", builder().destroyTime(2.0f) .booleanState(EAST) @@ -819,8 +820,8 @@ public final class Blocks { .booleanState(WATERLOGGED))); public static final Block NETHER_WART = register(new Block("nether_wart", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_3))); - public static final Block ENCHANTING_TABLE = register(new Block("enchanting_table", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(5.0f))); - public static final Block BREWING_STAND = register(new Block("brewing_stand", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(0.5f) + public static final Block ENCHANTING_TABLE = register(new Block("enchanting_table", builder().setBlockEntity(BlockEntityType.ENCHANTING_TABLE).requiresCorrectToolForDrops().destroyTime(5.0f))); + public static final Block BREWING_STAND = register(new Block("brewing_stand", builder().setBlockEntity(BlockEntityType.BREWING_STAND).requiresCorrectToolForDrops().destroyTime(0.5f) .booleanState(HAS_BOTTLE_0) .booleanState(HAS_BOTTLE_1) .booleanState(HAS_BOTTLE_2))); @@ -830,7 +831,7 @@ public final class Blocks { public static final Block LAVA_CAULDRON = register(new CauldronBlock("lava_cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); public static final Block POWDER_SNOW_CAULDRON = register(new CauldronBlock("powder_snow_cauldron", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .intState(LEVEL_CAULDRON))); - public static final Block END_PORTAL = register(new Block("end_portal", builder().setBlockEntity().destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK))); + public static final Block END_PORTAL = register(new Block("end_portal", builder().setBlockEntity(BlockEntityType.END_PORTAL).destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK))); public static final Block END_PORTAL_FRAME = register(new Block("end_portal_frame", builder().destroyTime(-1.0f) .booleanState(EYE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); @@ -848,7 +849,7 @@ public final class Blocks { .booleanState(WATERLOGGED))); public static final Block EMERALD_ORE = register(new Block("emerald_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); public static final Block DEEPSLATE_EMERALD_ORE = register(new Block("deepslate_emerald_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f))); - public static final Block ENDER_CHEST = register(new Block("ender_chest", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(22.5f) + public static final Block ENDER_CHEST = register(new Block("ender_chest", builder().setBlockEntity(BlockEntityType.ENDER_CHEST).requiresCorrectToolForDrops().destroyTime(22.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); public static final Block TRIPWIRE_HOOK = register(new Block("tripwire_hook", builder().pushReaction(PistonBehavior.DESTROY) @@ -879,10 +880,10 @@ public final class Blocks { .enumState(HALF) .enumState(STAIRS_SHAPE) .booleanState(WATERLOGGED))); - public static final Block COMMAND_BLOCK = register(new Block("command_block", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(-1.0f) + public static final Block COMMAND_BLOCK = register(new Block("command_block", builder().setBlockEntity(BlockEntityType.COMMAND_BLOCK).requiresCorrectToolForDrops().destroyTime(-1.0f) .booleanState(CONDITIONAL) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block BEACON = register(new Block("beacon", builder().setBlockEntity().destroyTime(3.0f))); + public static final Block BEACON = register(new Block("beacon", builder().setBlockEntity(BlockEntityType.BEACON).destroyTime(3.0f))); public static final Block COBBLESTONE_WALL = register(new Block("cobblestone_wall", builder().requiresCorrectToolForDrops().destroyTime(2.0f) .enumState(EAST_WALL) .enumState(NORTH_WALL) @@ -965,46 +966,46 @@ public final class Blocks { .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block SKELETON_SKULL = register(new SkullBlock("skeleton_skull", SkullBlock.Type.SKELETON, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block SKELETON_SKULL = register(new SkullBlock("skeleton_skull", SkullBlock.Type.SKELETON, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) .intState(ROTATION_16))); - public static final Block SKELETON_WALL_SKULL = register(new WallSkullBlock("skeleton_wall_skull", SkullBlock.Type.SKELETON, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block SKELETON_WALL_SKULL = register(new WallSkullBlock("skeleton_wall_skull", SkullBlock.Type.SKELETON, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block WITHER_SKELETON_SKULL = register(new SkullBlock("wither_skeleton_skull", SkullBlock.Type.WITHER_SKELETON, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block WITHER_SKELETON_SKULL = register(new SkullBlock("wither_skeleton_skull", SkullBlock.Type.WITHER_SKELETON, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) .intState(ROTATION_16))); - public static final Block WITHER_SKELETON_WALL_SKULL = register(new WallSkullBlock("wither_skeleton_wall_skull", SkullBlock.Type.WITHER_SKELETON, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block WITHER_SKELETON_WALL_SKULL = register(new WallSkullBlock("wither_skeleton_wall_skull", SkullBlock.Type.WITHER_SKELETON, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block ZOMBIE_HEAD = register(new SkullBlock("zombie_head", SkullBlock.Type.ZOMBIE, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block ZOMBIE_HEAD = register(new SkullBlock("zombie_head", SkullBlock.Type.ZOMBIE, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) .intState(ROTATION_16))); - public static final Block ZOMBIE_WALL_HEAD = register(new WallSkullBlock("zombie_wall_head", SkullBlock.Type.ZOMBIE, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block ZOMBIE_WALL_HEAD = register(new WallSkullBlock("zombie_wall_head", SkullBlock.Type.ZOMBIE, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block PLAYER_HEAD = register(new SkullBlock("player_head", SkullBlock.Type.PLAYER, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block PLAYER_HEAD = register(new SkullBlock("player_head", SkullBlock.Type.PLAYER, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) .intState(ROTATION_16))); - public static final Block PLAYER_WALL_HEAD = register(new WallSkullBlock("player_wall_head", SkullBlock.Type.PLAYER, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block PLAYER_WALL_HEAD = register(new WallSkullBlock("player_wall_head", SkullBlock.Type.PLAYER, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block CREEPER_HEAD = register(new SkullBlock("creeper_head", SkullBlock.Type.CREEPER, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block CREEPER_HEAD = register(new SkullBlock("creeper_head", SkullBlock.Type.CREEPER, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) .intState(ROTATION_16))); - public static final Block CREEPER_WALL_HEAD = register(new WallSkullBlock("creeper_wall_head", SkullBlock.Type.CREEPER, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block CREEPER_WALL_HEAD = register(new WallSkullBlock("creeper_wall_head", SkullBlock.Type.CREEPER, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block DRAGON_HEAD = register(new SkullBlock("dragon_head", SkullBlock.Type.DRAGON, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block DRAGON_HEAD = register(new SkullBlock("dragon_head", SkullBlock.Type.DRAGON, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) .intState(ROTATION_16))); - public static final Block DRAGON_WALL_HEAD = register(new WallSkullBlock("dragon_wall_head", SkullBlock.Type.DRAGON, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block DRAGON_WALL_HEAD = register(new WallSkullBlock("dragon_wall_head", SkullBlock.Type.DRAGON, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); - public static final Block PIGLIN_HEAD = register(new SkullBlock("piglin_head", SkullBlock.Type.PIGLIN, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block PIGLIN_HEAD = register(new SkullBlock("piglin_head", SkullBlock.Type.PIGLIN, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .booleanState(POWERED) .intState(ROTATION_16))); - public static final Block PIGLIN_WALL_HEAD = register(new WallSkullBlock("piglin_wall_head", SkullBlock.Type.PIGLIN, builder().setBlockEntity().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block PIGLIN_WALL_HEAD = register(new WallSkullBlock("piglin_wall_head", SkullBlock.Type.PIGLIN, builder().setBlockEntity(BlockEntityType.SKULL).destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); public static final Block ANVIL = register(new Block("anvil", builder().requiresCorrectToolForDrops().destroyTime(5.0f).pushReaction(PistonBehavior.BLOCK) @@ -1013,7 +1014,7 @@ public final class Blocks { .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); public static final Block DAMAGED_ANVIL = register(new Block("damaged_anvil", builder().requiresCorrectToolForDrops().destroyTime(5.0f).pushReaction(PistonBehavior.BLOCK) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block TRAPPED_CHEST = register(new ChestBlock("trapped_chest", builder().setBlockEntity().destroyTime(2.5f) + public static final Block TRAPPED_CHEST = register(new ChestBlock("trapped_chest", builder().setBlockEntity(BlockEntityType.TRAPPED_CHEST).destroyTime(2.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(CHEST_TYPE, ChestType.VALUES) .booleanState(WATERLOGGED))); @@ -1021,16 +1022,16 @@ public final class Blocks { .intState(POWER))); public static final Block HEAVY_WEIGHTED_PRESSURE_PLATE = register(new Block("heavy_weighted_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) .intState(POWER))); - public static final Block COMPARATOR = register(new Block("comparator", builder().setBlockEntity().pushReaction(PistonBehavior.DESTROY) + public static final Block COMPARATOR = register(new Block("comparator", builder().setBlockEntity(BlockEntityType.COMPARATOR).pushReaction(PistonBehavior.DESTROY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(MODE_COMPARATOR) .booleanState(POWERED))); - public static final Block DAYLIGHT_DETECTOR = register(new Block("daylight_detector", builder().setBlockEntity().destroyTime(0.2f) + public static final Block DAYLIGHT_DETECTOR = register(new Block("daylight_detector", builder().setBlockEntity(BlockEntityType.DAYLIGHT_DETECTOR).destroyTime(0.2f) .booleanState(INVERTED) .intState(POWER))); public static final Block REDSTONE_BLOCK = register(new Block("redstone_block", builder().requiresCorrectToolForDrops().destroyTime(5.0f))); public static final Block NETHER_QUARTZ_ORE = register(new Block("nether_quartz_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); - public static final Block HOPPER = register(new Block("hopper", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(3.0f) + public static final Block HOPPER = register(new Block("hopper", builder().setBlockEntity(BlockEntityType.HOPPER).requiresCorrectToolForDrops().destroyTime(3.0f) .booleanState(ENABLED) .enumState(FACING_HOPPER, Direction.DOWN, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); public static final Block QUARTZ_BLOCK = register(new Block("quartz_block", builder().requiresCorrectToolForDrops().destroyTime(0.8f))); @@ -1046,7 +1047,7 @@ public final class Blocks { .booleanState(POWERED) .enumState(RAIL_SHAPE_STRAIGHT) .booleanState(WATERLOGGED))); - public static final Block DROPPER = register(new Block("dropper", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(3.5f) + public static final Block DROPPER = register(new Block("dropper", builder().setBlockEntity(BlockEntityType.DROPPER).requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .booleanState(TRIGGERED))); public static final Block WHITE_TERRACOTTA = register(new Block("white_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.25f))); @@ -1264,69 +1265,69 @@ public final class Blocks { .enumState(DOUBLE_BLOCK_HALF))); public static final Block LARGE_FERN = register(new Block("large_fern", builder().pushReaction(PistonBehavior.DESTROY) .enumState(DOUBLE_BLOCK_HALF))); - public static final Block WHITE_BANNER = register(new BannerBlock("white_banner", 0, builder().setBlockEntity().destroyTime(1.0f) + public static final Block WHITE_BANNER = register(new BannerBlock("white_banner", 0, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .intState(ROTATION_16))); - public static final Block ORANGE_BANNER = register(new BannerBlock("orange_banner", 1, builder().setBlockEntity().destroyTime(1.0f) + public static final Block ORANGE_BANNER = register(new BannerBlock("orange_banner", 1, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .intState(ROTATION_16))); - public static final Block MAGENTA_BANNER = register(new BannerBlock("magenta_banner", 2, builder().setBlockEntity().destroyTime(1.0f) + public static final Block MAGENTA_BANNER = register(new BannerBlock("magenta_banner", 2, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .intState(ROTATION_16))); - public static final Block LIGHT_BLUE_BANNER = register(new BannerBlock("light_blue_banner", 3, builder().setBlockEntity().destroyTime(1.0f) + public static final Block LIGHT_BLUE_BANNER = register(new BannerBlock("light_blue_banner", 3, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .intState(ROTATION_16))); - public static final Block YELLOW_BANNER = register(new BannerBlock("yellow_banner", 4, builder().setBlockEntity().destroyTime(1.0f) + public static final Block YELLOW_BANNER = register(new BannerBlock("yellow_banner", 4, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .intState(ROTATION_16))); - public static final Block LIME_BANNER = register(new BannerBlock("lime_banner", 5, builder().setBlockEntity().destroyTime(1.0f) + public static final Block LIME_BANNER = register(new BannerBlock("lime_banner", 5, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .intState(ROTATION_16))); - public static final Block PINK_BANNER = register(new BannerBlock("pink_banner", 6, builder().setBlockEntity().destroyTime(1.0f) + public static final Block PINK_BANNER = register(new BannerBlock("pink_banner", 6, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .intState(ROTATION_16))); - public static final Block GRAY_BANNER = register(new BannerBlock("gray_banner", 7, builder().setBlockEntity().destroyTime(1.0f) + public static final Block GRAY_BANNER = register(new BannerBlock("gray_banner", 7, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .intState(ROTATION_16))); - public static final Block LIGHT_GRAY_BANNER = register(new BannerBlock("light_gray_banner", 8, builder().setBlockEntity().destroyTime(1.0f) + public static final Block LIGHT_GRAY_BANNER = register(new BannerBlock("light_gray_banner", 8, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .intState(ROTATION_16))); - public static final Block CYAN_BANNER = register(new BannerBlock("cyan_banner", 9, builder().setBlockEntity().destroyTime(1.0f) + public static final Block CYAN_BANNER = register(new BannerBlock("cyan_banner", 9, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .intState(ROTATION_16))); - public static final Block PURPLE_BANNER = register(new BannerBlock("purple_banner", 10, builder().setBlockEntity().destroyTime(1.0f) + public static final Block PURPLE_BANNER = register(new BannerBlock("purple_banner", 10, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .intState(ROTATION_16))); - public static final Block BLUE_BANNER = register(new BannerBlock("blue_banner", 11, builder().setBlockEntity().destroyTime(1.0f) + public static final Block BLUE_BANNER = register(new BannerBlock("blue_banner", 11, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .intState(ROTATION_16))); - public static final Block BROWN_BANNER = register(new BannerBlock("brown_banner", 12, builder().setBlockEntity().destroyTime(1.0f) + public static final Block BROWN_BANNER = register(new BannerBlock("brown_banner", 12, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .intState(ROTATION_16))); - public static final Block GREEN_BANNER = register(new BannerBlock("green_banner", 13, builder().setBlockEntity().destroyTime(1.0f) + public static final Block GREEN_BANNER = register(new BannerBlock("green_banner", 13, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .intState(ROTATION_16))); - public static final Block RED_BANNER = register(new BannerBlock("red_banner", 14, builder().setBlockEntity().destroyTime(1.0f) + public static final Block RED_BANNER = register(new BannerBlock("red_banner", 14, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .intState(ROTATION_16))); - public static final Block BLACK_BANNER = register(new BannerBlock("black_banner", 15, builder().setBlockEntity().destroyTime(1.0f) + public static final Block BLACK_BANNER = register(new BannerBlock("black_banner", 15, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .intState(ROTATION_16))); - public static final Block WHITE_WALL_BANNER = register(new BannerBlock("white_wall_banner", 0, builder().setBlockEntity().destroyTime(1.0f) + public static final Block WHITE_WALL_BANNER = register(new BannerBlock("white_wall_banner", 0, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block ORANGE_WALL_BANNER = register(new BannerBlock("orange_wall_banner", 1, builder().setBlockEntity().destroyTime(1.0f) + public static final Block ORANGE_WALL_BANNER = register(new BannerBlock("orange_wall_banner", 1, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block MAGENTA_WALL_BANNER = register(new BannerBlock("magenta_wall_banner", 2, builder().setBlockEntity().destroyTime(1.0f) + public static final Block MAGENTA_WALL_BANNER = register(new BannerBlock("magenta_wall_banner", 2, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block LIGHT_BLUE_WALL_BANNER = register(new BannerBlock("light_blue_wall_banner", 3, builder().setBlockEntity().destroyTime(1.0f) + public static final Block LIGHT_BLUE_WALL_BANNER = register(new BannerBlock("light_blue_wall_banner", 3, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block YELLOW_WALL_BANNER = register(new BannerBlock("yellow_wall_banner", 4, builder().setBlockEntity().destroyTime(1.0f) + public static final Block YELLOW_WALL_BANNER = register(new BannerBlock("yellow_wall_banner", 4, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block LIME_WALL_BANNER = register(new BannerBlock("lime_wall_banner", 5, builder().setBlockEntity().destroyTime(1.0f) + public static final Block LIME_WALL_BANNER = register(new BannerBlock("lime_wall_banner", 5, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block PINK_WALL_BANNER = register(new BannerBlock("pink_wall_banner", 6, builder().setBlockEntity().destroyTime(1.0f) + public static final Block PINK_WALL_BANNER = register(new BannerBlock("pink_wall_banner", 6, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block GRAY_WALL_BANNER = register(new BannerBlock("gray_wall_banner", 7, builder().setBlockEntity().destroyTime(1.0f) + public static final Block GRAY_WALL_BANNER = register(new BannerBlock("gray_wall_banner", 7, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block LIGHT_GRAY_WALL_BANNER = register(new BannerBlock("light_gray_wall_banner", 8, builder().setBlockEntity().destroyTime(1.0f) + public static final Block LIGHT_GRAY_WALL_BANNER = register(new BannerBlock("light_gray_wall_banner", 8, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block CYAN_WALL_BANNER = register(new BannerBlock("cyan_wall_banner", 9, builder().setBlockEntity().destroyTime(1.0f) + public static final Block CYAN_WALL_BANNER = register(new BannerBlock("cyan_wall_banner", 9, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block PURPLE_WALL_BANNER = register(new BannerBlock("purple_wall_banner", 10, builder().setBlockEntity().destroyTime(1.0f) + public static final Block PURPLE_WALL_BANNER = register(new BannerBlock("purple_wall_banner", 10, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block BLUE_WALL_BANNER = register(new BannerBlock("blue_wall_banner", 11, builder().setBlockEntity().destroyTime(1.0f) + public static final Block BLUE_WALL_BANNER = register(new BannerBlock("blue_wall_banner", 11, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block BROWN_WALL_BANNER = register(new BannerBlock("brown_wall_banner", 12, builder().setBlockEntity().destroyTime(1.0f) + public static final Block BROWN_WALL_BANNER = register(new BannerBlock("brown_wall_banner", 12, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block GREEN_WALL_BANNER = register(new BannerBlock("green_wall_banner", 13, builder().setBlockEntity().destroyTime(1.0f) + public static final Block GREEN_WALL_BANNER = register(new BannerBlock("green_wall_banner", 13, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block RED_WALL_BANNER = register(new BannerBlock("red_wall_banner", 14, builder().setBlockEntity().destroyTime(1.0f) + public static final Block RED_WALL_BANNER = register(new BannerBlock("red_wall_banner", 14, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block BLACK_WALL_BANNER = register(new BannerBlock("black_wall_banner", 15, builder().setBlockEntity().destroyTime(1.0f) + public static final Block BLACK_WALL_BANNER = register(new BannerBlock("black_wall_banner", 15, builder().setBlockEntity(BlockEntityType.BANNER).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); public static final Block RED_SANDSTONE = register(new Block("red_sandstone", builder().requiresCorrectToolForDrops().destroyTime(0.8f))); public static final Block CHISELED_RED_SANDSTONE = register(new Block("chiseled_red_sandstone", builder().requiresCorrectToolForDrops().destroyTime(0.8f))); @@ -1578,11 +1579,11 @@ public final class Blocks { public static final Block BEETROOTS = register(new Block("beetroots", builder().pushReaction(PistonBehavior.DESTROY) .intState(AGE_3))); public static final Block DIRT_PATH = register(new Block("dirt_path", builder().destroyTime(0.65f))); - public static final Block END_GATEWAY = register(new Block("end_gateway", builder().setBlockEntity().destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK))); - public static final Block REPEATING_COMMAND_BLOCK = register(new Block("repeating_command_block", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(-1.0f) + public static final Block END_GATEWAY = register(new Block("end_gateway", builder().setBlockEntity(BlockEntityType.END_GATEWAY).destroyTime(-1.0f).pushReaction(PistonBehavior.BLOCK))); + public static final Block REPEATING_COMMAND_BLOCK = register(new Block("repeating_command_block", builder().setBlockEntity(BlockEntityType.COMMAND_BLOCK).requiresCorrectToolForDrops().destroyTime(-1.0f) .booleanState(CONDITIONAL) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block CHAIN_COMMAND_BLOCK = register(new Block("chain_command_block", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(-1.0f) + public static final Block CHAIN_COMMAND_BLOCK = register(new Block("chain_command_block", builder().setBlockEntity(BlockEntityType.COMMAND_BLOCK).requiresCorrectToolForDrops().destroyTime(-1.0f) .booleanState(CONDITIONAL) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); public static final Block FROSTED_ICE = register(new Block("frosted_ice", builder().destroyTime(0.5f) @@ -1596,39 +1597,39 @@ public final class Blocks { public static final Block OBSERVER = register(new Block("observer", builder().requiresCorrectToolForDrops().destroyTime(3.0f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .booleanState(POWERED))); - public static final Block SHULKER_BOX = register(new Block("shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block SHULKER_BOX = register(new Block("shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block WHITE_SHULKER_BOX = register(new Block("white_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block WHITE_SHULKER_BOX = register(new Block("white_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block ORANGE_SHULKER_BOX = register(new Block("orange_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block ORANGE_SHULKER_BOX = register(new Block("orange_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block MAGENTA_SHULKER_BOX = register(new Block("magenta_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block MAGENTA_SHULKER_BOX = register(new Block("magenta_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block LIGHT_BLUE_SHULKER_BOX = register(new Block("light_blue_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block LIGHT_BLUE_SHULKER_BOX = register(new Block("light_blue_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block YELLOW_SHULKER_BOX = register(new Block("yellow_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block YELLOW_SHULKER_BOX = register(new Block("yellow_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block LIME_SHULKER_BOX = register(new Block("lime_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block LIME_SHULKER_BOX = register(new Block("lime_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block PINK_SHULKER_BOX = register(new Block("pink_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block PINK_SHULKER_BOX = register(new Block("pink_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block GRAY_SHULKER_BOX = register(new Block("gray_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block GRAY_SHULKER_BOX = register(new Block("gray_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block LIGHT_GRAY_SHULKER_BOX = register(new Block("light_gray_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block LIGHT_GRAY_SHULKER_BOX = register(new Block("light_gray_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block CYAN_SHULKER_BOX = register(new Block("cyan_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block CYAN_SHULKER_BOX = register(new Block("cyan_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block PURPLE_SHULKER_BOX = register(new Block("purple_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block PURPLE_SHULKER_BOX = register(new Block("purple_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block BLUE_SHULKER_BOX = register(new Block("blue_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block BLUE_SHULKER_BOX = register(new Block("blue_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block BROWN_SHULKER_BOX = register(new Block("brown_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block BROWN_SHULKER_BOX = register(new Block("brown_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block GREEN_SHULKER_BOX = register(new Block("green_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block GREEN_SHULKER_BOX = register(new Block("green_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block RED_SHULKER_BOX = register(new Block("red_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block RED_SHULKER_BOX = register(new Block("red_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); - public static final Block BLACK_SHULKER_BOX = register(new Block("black_shulker_box", builder().setBlockEntity().destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block BLACK_SHULKER_BOX = register(new Block("black_shulker_box", builder().setBlockEntity(BlockEntityType.SHULKER_BOX).destroyTime(2.0f).pushReaction(PistonBehavior.DESTROY) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN))); public static final Block WHITE_GLAZED_TERRACOTTA = register(new Block("white_glazed_terracotta", builder().requiresCorrectToolForDrops().destroyTime(1.4f).pushReaction(PistonBehavior.PUSH_ONLY) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); @@ -1787,7 +1788,7 @@ public final class Blocks { .intState(PICKLES) .booleanState(WATERLOGGED))); public static final Block BLUE_ICE = register(new Block("blue_ice", builder().destroyTime(2.8f))); - public static final Block CONDUIT = register(new Block("conduit", builder().setBlockEntity().destroyTime(3.0f) + public static final Block CONDUIT = register(new Block("conduit", builder().setBlockEntity(BlockEntityType.CONDUIT).destroyTime(3.0f) .booleanState(WATERLOGGED))); public static final Block BAMBOO_SAPLING = register(new Block("bamboo_sapling", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY).pickItem(() -> Items.BAMBOO))); public static final Block BAMBOO = register(new Block("bamboo", builder().destroyTime(1.0f).pushReaction(PistonBehavior.DESTROY) @@ -2005,13 +2006,13 @@ public final class Blocks { .booleanState(WATERLOGGED))); public static final Block LOOM = register(new Block("loom", builder().destroyTime(2.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block BARREL = register(new Block("barrel", builder().setBlockEntity().destroyTime(2.5f) + public static final Block BARREL = register(new Block("barrel", builder().setBlockEntity(BlockEntityType.BARREL).destroyTime(2.5f) .enumState(FACING, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN) .booleanState(OPEN))); - public static final Block SMOKER = register(new Block("smoker", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(3.5f) + public static final Block SMOKER = register(new Block("smoker", builder().setBlockEntity(BlockEntityType.SMOKER).requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(LIT))); - public static final Block BLAST_FURNACE = register(new Block("blast_furnace", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(3.5f) + public static final Block BLAST_FURNACE = register(new Block("blast_furnace", builder().setBlockEntity(BlockEntityType.BLAST_FURNACE).requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(LIT))); public static final Block CARTOGRAPHY_TABLE = register(new Block("cartography_table", builder().destroyTime(2.5f))); @@ -2019,14 +2020,14 @@ public final class Blocks { public static final Block GRINDSTONE = register(new Block("grindstone", builder().requiresCorrectToolForDrops().destroyTime(2.0f).pushReaction(PistonBehavior.BLOCK) .enumState(ATTACH_FACE) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block LECTERN = register(new LecternBlock("lectern", builder().setBlockEntity().destroyTime(2.5f) + public static final Block LECTERN = register(new LecternBlock("lectern", builder().setBlockEntity(BlockEntityType.LECTERN).destroyTime(2.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(HAS_BOOK) .booleanState(POWERED))); public static final Block SMITHING_TABLE = register(new Block("smithing_table", builder().destroyTime(2.5f))); public static final Block STONECUTTER = register(new Block("stonecutter", builder().requiresCorrectToolForDrops().destroyTime(3.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); - public static final Block BELL = register(new Block("bell", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(5.0f).pushReaction(PistonBehavior.DESTROY) + public static final Block BELL = register(new Block("bell", builder().setBlockEntity(BlockEntityType.BELL).requiresCorrectToolForDrops().destroyTime(5.0f).pushReaction(PistonBehavior.DESTROY) .enumState(BELL_ATTACHMENT) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(POWERED))); @@ -2036,12 +2037,12 @@ public final class Blocks { public static final Block SOUL_LANTERN = register(new Block("soul_lantern", builder().requiresCorrectToolForDrops().destroyTime(3.5f).pushReaction(PistonBehavior.DESTROY) .booleanState(HANGING) .booleanState(WATERLOGGED))); - public static final Block CAMPFIRE = register(new Block("campfire", builder().setBlockEntity().destroyTime(2.0f) + public static final Block CAMPFIRE = register(new Block("campfire", builder().setBlockEntity(BlockEntityType.CAMPFIRE).destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(LIT) .booleanState(SIGNAL_FIRE) .booleanState(WATERLOGGED))); - public static final Block SOUL_CAMPFIRE = register(new Block("soul_campfire", builder().setBlockEntity().destroyTime(2.0f) + public static final Block SOUL_CAMPFIRE = register(new Block("soul_campfire", builder().setBlockEntity(BlockEntityType.CAMPFIRE).destroyTime(2.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(LIT) .booleanState(SIGNAL_FIRE) @@ -2155,30 +2156,30 @@ public final class Blocks { .enumState(DOOR_HINGE) .booleanState(OPEN) .booleanState(POWERED))); - public static final Block CRIMSON_SIGN = register(new Block("crimson_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block CRIMSON_SIGN = register(new Block("crimson_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f) .intState(ROTATION_16) .booleanState(WATERLOGGED))); - public static final Block WARPED_SIGN = register(new Block("warped_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block WARPED_SIGN = register(new Block("warped_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f) .intState(ROTATION_16) .booleanState(WATERLOGGED))); - public static final Block CRIMSON_WALL_SIGN = register(new Block("crimson_wall_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block CRIMSON_WALL_SIGN = register(new Block("crimson_wall_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block WARPED_WALL_SIGN = register(new Block("warped_wall_sign", builder().setBlockEntity().destroyTime(1.0f) + public static final Block WARPED_WALL_SIGN = register(new Block("warped_wall_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block STRUCTURE_BLOCK = register(new Block("structure_block", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(-1.0f) + public static final Block STRUCTURE_BLOCK = register(new Block("structure_block", builder().setBlockEntity(BlockEntityType.STRUCTURE_BLOCK).requiresCorrectToolForDrops().destroyTime(-1.0f) .enumState(STRUCTUREBLOCK_MODE))); - public static final Block JIGSAW = register(new Block("jigsaw", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(-1.0f) + public static final Block JIGSAW = register(new Block("jigsaw", builder().setBlockEntity(BlockEntityType.JIGSAW).requiresCorrectToolForDrops().destroyTime(-1.0f) .enumState(ORIENTATION, FrontAndTop.VALUES))); public static final Block COMPOSTER = register(new Block("composter", builder().destroyTime(0.6f) .intState(LEVEL_COMPOSTER))); public static final Block TARGET = register(new Block("target", builder().destroyTime(0.5f) .intState(POWER))); - public static final Block BEE_NEST = register(new Block("bee_nest", builder().setBlockEntity().destroyTime(0.3f) + public static final Block BEE_NEST = register(new Block("bee_nest", builder().setBlockEntity(BlockEntityType.BEEHIVE).destroyTime(0.3f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .intState(LEVEL_HONEY))); - public static final Block BEEHIVE = register(new Block("beehive", builder().setBlockEntity().destroyTime(0.6f) + public static final Block BEEHIVE = register(new Block("beehive", builder().setBlockEntity(BlockEntityType.BEEHIVE).destroyTime(0.6f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .intState(LEVEL_HONEY))); public static final Block HONEY_BLOCK = register(new HoneyBlock("honey_block", builder())); @@ -2422,11 +2423,11 @@ public final class Blocks { public static final Block CALCITE = register(new Block("calcite", builder().requiresCorrectToolForDrops().destroyTime(0.75f))); public static final Block TINTED_GLASS = register(new Block("tinted_glass", builder().destroyTime(0.3f))); public static final Block POWDER_SNOW = register(new Block("powder_snow", builder().destroyTime(0.25f))); - public static final Block SCULK_SENSOR = register(new Block("sculk_sensor", builder().setBlockEntity().destroyTime(1.5f) + public static final Block SCULK_SENSOR = register(new Block("sculk_sensor", builder().setBlockEntity(BlockEntityType.SCULK_SENSOR).destroyTime(1.5f) .intState(POWER) .enumState(SCULK_SENSOR_PHASE) .booleanState(WATERLOGGED))); - public static final Block CALIBRATED_SCULK_SENSOR = register(new Block("calibrated_sculk_sensor", builder().setBlockEntity().destroyTime(1.5f) + public static final Block CALIBRATED_SCULK_SENSOR = register(new Block("calibrated_sculk_sensor", builder().setBlockEntity(BlockEntityType.CALIBRATED_SCULK_SENSOR).destroyTime(1.5f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .intState(POWER) .enumState(SCULK_SENSOR_PHASE) @@ -2440,9 +2441,9 @@ public final class Blocks { .booleanState(UP) .booleanState(WATERLOGGED) .booleanState(WEST))); - public static final Block SCULK_CATALYST = register(new Block("sculk_catalyst", builder().setBlockEntity().destroyTime(3.0f) + public static final Block SCULK_CATALYST = register(new Block("sculk_catalyst", builder().setBlockEntity(BlockEntityType.SCULK_CATALYST).destroyTime(3.0f) .booleanState(BLOOM))); - public static final Block SCULK_SHRIEKER = register(new Block("sculk_shrieker", builder().setBlockEntity().destroyTime(3.0f) + public static final Block SCULK_SHRIEKER = register(new Block("sculk_shrieker", builder().setBlockEntity(BlockEntityType.SCULK_SHRIEKER).destroyTime(3.0f) .booleanState(CAN_SUMMON) .booleanState(SHRIEKING) .booleanState(WATERLOGGED))); @@ -2794,18 +2795,18 @@ public final class Blocks { .enumState(AXIS, Axis.VALUES))); public static final Block FROGSPAWN = register(new Block("frogspawn", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block REINFORCED_DEEPSLATE = register(new Block("reinforced_deepslate", builder().destroyTime(55.0f))); - public static final Block DECORATED_POT = register(new Block("decorated_pot", builder().setBlockEntity().pushReaction(PistonBehavior.DESTROY) + public static final Block DECORATED_POT = register(new Block("decorated_pot", builder().setBlockEntity(BlockEntityType.DECORATED_POT).pushReaction(PistonBehavior.DESTROY) .booleanState(CRACKED) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(WATERLOGGED))); - public static final Block CRAFTER = register(new Block("crafter", builder().setBlockEntity().destroyTime(1.5f) + public static final Block CRAFTER = register(new Block("crafter", builder().setBlockEntity(BlockEntityType.CRAFTER).destroyTime(1.5f) .booleanState(CRAFTING) .enumState(ORIENTATION, FrontAndTop.VALUES) .booleanState(TRIGGERED))); - public static final Block TRIAL_SPAWNER = register(new Block("trial_spawner", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(50.0f) + public static final Block TRIAL_SPAWNER = register(new Block("trial_spawner", builder().setBlockEntity(BlockEntityType.TRIAL_SPAWNER).destroyTime(50.0f) .booleanState(OMINOUS) .enumState(TRIAL_SPAWNER_STATE))); - public static final Block VAULT = register(new Block("vault", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(50.0f) + public static final Block VAULT = register(new Block("vault", builder().setBlockEntity(BlockEntityType.VAULT).destroyTime(50.0f) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .booleanState(OMINOUS) .enumState(VAULT_STATE))); 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 8028a4355..782f664fc 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 @@ -16,7 +16,6 @@ public class GeyserJavaBlockState implements JavaBlockState { boolean canBreakWithHand; String pickItem; String pistonBehavior; - boolean hasBlockEntity; private GeyserJavaBlockState(Builder builder) { this.identifier = builder.identifier; @@ -28,7 +27,6 @@ public class GeyserJavaBlockState implements JavaBlockState { this.canBreakWithHand = builder.canBreakWithHand; this.pickItem = builder.pickItem; this.pistonBehavior = builder.pistonBehavior; - this.hasBlockEntity = builder.hasBlockEntity; } @Override @@ -76,9 +74,10 @@ public class GeyserJavaBlockState implements JavaBlockState { return pistonBehavior; } + @SuppressWarnings("removal") @Override public boolean hasBlockEntity() { - return hasBlockEntity; + return false; } public static class Builder implements JavaBlockState.Builder { @@ -91,7 +90,6 @@ public class GeyserJavaBlockState implements JavaBlockState { private boolean canBreakWithHand; private String pickItem; private String pistonBehavior; - private boolean hasBlockEntity; @Override public Builder identifier(@NonNull String identifier) { @@ -147,9 +145,13 @@ public class GeyserJavaBlockState implements JavaBlockState { return this; } + @SuppressWarnings("removal") @Override public Builder hasBlockEntity(boolean hasBlockEntity) { - this.hasBlockEntity = hasBlockEntity; + // keep the current behavior + if (this.pistonBehavior == null && hasBlockEntity) { + this.pistonBehavior = "BLOCK"; + } return this; } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java b/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java index ee99b652a..a005fc103 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/Block.java @@ -29,6 +29,7 @@ import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; import net.kyori.adventure.key.Key; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; @@ -41,6 +42,7 @@ import org.geysermc.geyser.level.physics.PistonBehavior; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; import org.intellij.lang.annotations.Subst; import java.util.*; @@ -55,7 +57,7 @@ public class Block { * Can you harvest this with your hand. */ private final boolean requiresCorrectToolForDrops; - private final boolean hasBlockEntity; + private final @Nullable BlockEntityType blockEntityType; private final float destroyTime; private final @NonNull PistonBehavior pushReaction; /** @@ -75,7 +77,7 @@ public class Block { public Block(@Subst("empty") String javaIdentifier, Builder builder) { this.javaIdentifier = Key.key(javaIdentifier); this.requiresCorrectToolForDrops = builder.requiresCorrectToolForDrops; - this.hasBlockEntity = builder.hasBlockEntity; + this.blockEntityType = builder.blockEntityType; this.destroyTime = builder.destroyTime; this.pushReaction = builder.pushReaction; this.pickItem = builder.pickItem; @@ -181,7 +183,12 @@ public class Block { } public boolean hasBlockEntity() { - return hasBlockEntity; + return blockEntityType != null; + } + + @Nullable + public BlockEntityType blockEntityType() { + return blockEntityType; } public float destroyTime() { @@ -227,7 +234,7 @@ public class Block { public static final class Builder { private final Map, List>> states = new LinkedHashMap<>(); private boolean requiresCorrectToolForDrops = false; - private boolean hasBlockEntity = false; + private BlockEntityType blockEntityType = null; private PistonBehavior pushReaction = PistonBehavior.NORMAL; private float destroyTime; private Supplier pickItem; @@ -271,8 +278,8 @@ public class Block { return this; } - public Builder setBlockEntity() { - this.hasBlockEntity = true; + public Builder setBlockEntity(BlockEntityType blockEntityType) { + this.blockEntityType = blockEntityType; return this; } diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java index 2a4b1774d..7229e9e50 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java @@ -65,14 +65,6 @@ public final class BlockState { return (T) get(property); } - public boolean getValue(Property property, boolean def) { - var value = get(property); - if (value == null) { - return def; - } - return (Boolean) value; - } - public > T getValue(Property property, T def) { var value = get(property); if (value == null) { 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 272522429..d7dc989da 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 @@ -435,9 +435,6 @@ public final class BlockRegistryPopulator { if (!javaBlockState.canBreakWithHand()) { builder.requiresCorrectToolForDrops(); } - if (javaBlockState.hasBlockEntity()) { - builder.setBlockEntity(); - } String cleanJavaIdentifier = BlockUtils.getCleanIdentifier(javaBlockState.identifier()); String pickItem = javaBlockState.pickItem(); Block block = new Block(cleanJavaIdentifier, builder) { 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 f0d632041..de0ce62b3 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 @@ -37,7 +37,6 @@ 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(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, BlockState blockState) { if (javaNbt == null) { 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 33c884c55..c22d906cf 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 @@ -34,7 +34,6 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType @BlockEntity(type = BlockEntityType.DECORATED_POT) public class DecoratedPotBlockEntityTranslator extends BlockEntityTranslator { - @Override public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) { if (javaNbt == null) { 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 6fea10e2e..9cbd5f433 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 @@ -27,7 +27,6 @@ package org.geysermc.geyser.translator.level.block.entity; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; -import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.level.block.property.ChestType; import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.level.block.type.BlockState; @@ -40,12 +39,8 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType */ @BlockEntity(type = { BlockEntityType.CHEST, BlockEntityType.TRAPPED_CHEST }) public class DoubleChestBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { - @Override public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) { - if (!(blockState.is(Blocks.CHEST) || blockState.is(Blocks.TRAPPED_CHEST))) { - return; - } if (blockState.getValue(Properties.CHEST_TYPE) != ChestType.SINGLE) { int x = (int) bedrockNbt.get("x"); int z = (int) bedrockNbt.get("z"); 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 cac40b350..e6d19e492 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 @@ -30,7 +30,6 @@ import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.level.block.type.BlockState; -import org.geysermc.geyser.level.physics.Direction; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.inventory.ShulkerInventoryTranslator; import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; @@ -43,6 +42,6 @@ public class ShulkerBoxBlockEntityTranslator extends BlockEntityTranslator imple */ @Override public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, BlockState blockState) { - bedrockNbt.putByte("facing", (byte) blockState.getValue(Properties.FACING, Direction.UP).ordinal()); + bedrockNbt.putByte("facing", (byte) blockState.getValue(Properties.FACING).ordinal()); } } 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 cdbb20c44..c2d457202 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 @@ -50,7 +50,6 @@ import java.util.concurrent.ExecutionException; @BlockEntity(type = BlockEntityType.SKULL) public class SkullBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { - @Override public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) { Integer rotation = blockState.getValue(Properties.ROTATION_16); 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 4b6a630ba..6b26f2b2c 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 @@ -39,7 +39,6 @@ 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, @Nullable NbtMap javaNbt, BlockState blockState) { if (javaNbt == 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 index 79fb3da6b..dcf4f85ff 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 @@ -39,7 +39,6 @@ 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, @Nullable NbtMap javaNbt, BlockState blockState) { if (javaNbt == null) { 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 a4c158a15..dd58bfa6f 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 @@ -33,7 +33,6 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType @BlockEntity(type = BlockEntityType.TRIAL_SPAWNER) public class TrialSpawnerBlockEntityTranslator extends BlockEntityTranslator { - @Override public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) { if (javaNbt == null) { 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 4210a8fe0..24d419c24 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 @@ -33,11 +33,11 @@ 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.Blocks; import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator; -import org.geysermc.geyser.translator.level.block.entity.RequiresBlockState; import org.geysermc.geyser.translator.level.block.entity.SkullBlockEntityTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; @@ -59,11 +59,11 @@ public class JavaBlockEntityDataTranslator extends PacketTranslator> 4) - yOffset]; - BlockState blockState = BlockRegistries.BLOCK_STATES.get(section.get(x, y & 0xF, z)); + BlockState blockState = BlockRegistries.BLOCK_STATES.getOrDefault(section.get(x, y & 0xF, z), Blocks.AIR.defaultBlockState()); // Note that, since 1.20.5, tags can be null, but Bedrock still needs a default tag to render the item // Also, some properties - like banner base colors - are part of the tag and is processed here. BlockEntityTranslator blockEntityTranslator = BlockEntityUtils.getBlockEntityTranslator(type); - bedrockBlockEntities.add(blockEntityTranslator.getBlockEntityTag(session, type, x + chunkBlockX, y, z + chunkBlockZ, tag, blockState)); - // Check for custom skulls - if (session.getPreferencesCache().showCustomSkulls() && type == BlockEntityType.SKULL && tag != null && tag.containsKey("profile")) { - BlockDefinition blockDefinition = SkullBlockEntityTranslator.translateSkull(session, tag, Vector3i.from(x + chunkBlockX, y, z + chunkBlockZ), blockState); - if (blockDefinition != null) { - int bedrockSectionY = (y >> 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(subChunkIndex); - sections[bedrockSectionY] = bedrockSection; + // The Java server can send block entity data for blocks that aren't actually those blocks. + // A Java client ignores these + if (type == blockState.block().blockEntityType()) { + bedrockBlockEntities.add(blockEntityTranslator.getBlockEntityTag(session, type, x + chunkBlockX, y, z + chunkBlockZ, tag, blockState)); + + // Check for custom skulls + if (session.getPreferencesCache().showCustomSkulls() && type == BlockEntityType.SKULL && tag != null && tag.containsKey("profile")) { + BlockDefinition blockDefinition = SkullBlockEntityTranslator.translateSkull(session, tag, Vector3i.from(x + chunkBlockX, y, z + chunkBlockZ), blockState); + if (blockDefinition != null) { + int bedrockSectionY = (y >> 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(subChunkIndex); + sections[bedrockSectionY] = bedrockSection; + } + bedrockSection.setFullBlock(x, y & 0xF, z, 0, blockDefinition.getRuntimeId()); } - bedrockSection.setFullBlock(x, y & 0xF, z, 0, blockDefinition.getRuntimeId()); } } } From 57cb8549ec5c6952e2593ee0a41a29290cbc34f9 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Wed, 19 Jun 2024 19:56:33 -0400 Subject: [PATCH 119/233] Update Floodgate download location --- core/src/main/java/org/geysermc/geyser/Constants.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/Constants.java b/core/src/main/java/org/geysermc/geyser/Constants.java index 5de8e6e6b..588b25172 100644 --- a/core/src/main/java/org/geysermc/geyser/Constants.java +++ b/core/src/main/java/org/geysermc/geyser/Constants.java @@ -34,7 +34,7 @@ public final class Constants { public static final String NEWS_OVERVIEW_URL = "https://api.geysermc.org/v2/news/"; public static final String NEWS_PROJECT_NAME = "geyser"; - public static final String FLOODGATE_DOWNLOAD_LOCATION = "https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/master/"; + public static final String FLOODGATE_DOWNLOAD_LOCATION = "https://geysermc.org/download#floodgate"; public static final String GEYSER_DOWNLOAD_LOCATION = "https://geysermc.org/download"; public static final String UPDATE_PERMISSION = "geyser.update"; From 2e6cf2f4caac13b2f51606862852560cc1b17203 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Wed, 19 Jun 2024 22:43:47 -0400 Subject: [PATCH 120/233] 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 ff44a3257..23cb22f9c 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit ff44a32574d0cac242aa99d8f97af0b5c636c0cf +Subproject commit 23cb22f9ceeb7f24b896a69a711944d7f3e756ed From ded6f6bb7cc36b6a4e2ba2bca07c72b85cba1732 Mon Sep 17 00:00:00 2001 From: Eclipse <116838833+eclipseisoffline@users.noreply.github.com> Date: Thu, 20 Jun 2024 14:46:54 +0000 Subject: [PATCH 121/233] Fix NPEs caused by custom head blocks from Polymer (#4764) * Add null checks to fix NPEs caused by custom head blocks from Polymer * Make sure block state is never null, remove now unnecessary null checks * Remove unnecessary default fallback in skull block entity translator --- .../geyser/entity/type/player/SkullPlayerEntity.java | 2 +- .../geysermc/geyser/level/block/type/BlockState.java | 10 +++++++++- .../bedrock/entity/player/BedrockActionTranslator.java | 4 ++-- .../java/level/JavaBlockDestructionTranslator.java | 4 +--- .../java/level/JavaBlockEntityDataTranslator.java | 5 +---- .../java/level/JavaLevelChunkWithLightTranslator.java | 3 +-- 6 files changed, 15 insertions(+), 13 deletions(-) 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 f2f93b266..1c5060de0 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 @@ -152,7 +152,7 @@ public class SkullPlayerEntity extends PlayerEntity { case EAST -> x -= 0.24f; } } else { - rotation = (180f + (blockState.getValue(Properties.ROTATION_16) * 22.5f)) % 360; + rotation = (180f + blockState.getValue(Properties.ROTATION_16, 0) * 22.5f) % 360; } moveAbsolute(Vector3f.from(x, y, z), rotation, 0, rotation, true, true); diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java index 7229e9e50..2513e3ceb 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/BlockState.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.level.block.type; +import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.level.block.property.Property; import org.geysermc.geyser.registry.BlockRegistries; @@ -184,7 +185,14 @@ public final class BlockState { return builder.toString(); } + /** + * Null-safe method that looks up a Java block state ID in the BLOCK_STATES registry, and defaults to air if not found. + * + * @param javaId the Java block state ID to look up. + * @return the corresponding block state, or air if the given ID wasn't registered and returned null. + */ + @NonNull public static BlockState of(int javaId) { - return BlockRegistries.BLOCK_STATES.get(javaId); + return BlockRegistries.BLOCK_STATES.getOrDefault(javaId, BlockRegistries.BLOCK_STATES.get(Block.JAVA_AIR_ID)); } } 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 959797d41..6834d3190 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 @@ -160,7 +160,7 @@ public class BedrockActionTranslator extends PacketTranslator> 4) - yOffset]; - BlockState blockState = BlockRegistries.BLOCK_STATES.getOrDefault(section.get(x, y & 0xF, z), Blocks.AIR.defaultBlockState()); + BlockState blockState = BlockState.of(section.get(x, y & 0xF, z)); // Note that, since 1.20.5, tags can be null, but Bedrock still needs a default tag to render the item // Also, some properties - like banner base colors - are part of the tag and is processed here. From fc529a661cc85655ef95e72cc96caa20d5f08218 Mon Sep 17 00:00:00 2001 From: Alex <40795980+AlexProgrammerDE@users.noreply.github.com> Date: Thu, 20 Jun 2024 19:29:42 +0200 Subject: [PATCH 122/233] Fix build errors reporting to the wrong directory by updating blossom (#4771) * Fix build errors reporting to the wrong directory by updating blossom * Add info comment --- core/build.gradle.kts | 28 ++++++++------ .../org/geysermc/geyser/BuildData.java | 37 +++++++++++++++++++ .../java/org/geysermc/geyser/GeyserImpl.java | 12 +++--- gradle/libs.versions.toml | 2 +- 4 files changed, 60 insertions(+), 19 deletions(-) create mode 100644 core/src/main/java-templates/org/geysermc/geyser/BuildData.java diff --git a/core/build.gradle.kts b/core/build.gradle.kts index a27c4fc89..e7b63ff56 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,6 +1,6 @@ -import net.kyori.blossom.BlossomExtension - plugins { + // Allow blossom to mark sources root of templates + idea alias(libs.plugins.blossom) id("geyser.publish-conventions") } @@ -84,16 +84,20 @@ tasks.processResources { } } -configure { - val mainFile = "src/main/java/org/geysermc/geyser/GeyserImpl.java" - val info = GitInfo() - - replaceToken("\${version}", "${project.version} (${info.gitVersion})", mainFile) - replaceToken("\${gitVersion}", info.gitVersion, mainFile) - replaceToken("\${buildNumber}", info.buildNumber, mainFile) - replaceToken("\${branch}", info.branch, mainFile) - replaceToken("\${commit}", info.commit, mainFile) - replaceToken("\${repository}", info.repository, mainFile) +sourceSets { + main { + blossom { + val info = GitInfo() + javaSources { + property("version", "${project.version} (${info.gitVersion})") + property("gitVersion", info.gitVersion) + property("buildNumber", info.buildNumber.toString()) + property("branch", info.branch) + property("commit", info.commit) + property("repository", info.repository) + } + } + } } fun Project.buildNumber(): Int = diff --git a/core/src/main/java-templates/org/geysermc/geyser/BuildData.java b/core/src/main/java-templates/org/geysermc/geyser/BuildData.java new file mode 100644 index 000000000..d489d8d17 --- /dev/null +++ b/core/src/main/java-templates/org/geysermc/geyser/BuildData.java @@ -0,0 +1,37 @@ +/* + * 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; + +// The constants are replaced before compilation +public class BuildData { + 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 }}"; + public static final String COMMIT = "{{ commit }}"; + public static final String REPOSITORY = "{{ repository }}"; +} diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index cc5f7ea33..0975ea5a9 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -115,13 +115,13 @@ public class GeyserImpl implements GeyserApi { .enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES); public static final String NAME = "Geyser"; - public static final String GIT_VERSION = "${gitVersion}"; - public static final String VERSION = "${version}"; + public static final String GIT_VERSION = BuildData.GIT_VERSION; + public static final String VERSION = BuildData.VERSION; - public static final String BUILD_NUMBER = "${buildNumber}"; - public static final String BRANCH = "${branch}"; - public static final String COMMIT = "${commit}"; - public static final String REPOSITORY = "${repository}"; + public static final String BUILD_NUMBER = BuildData.BUILD_NUMBER; + public static final String BRANCH = BuildData.BRANCH; + public static final String COMMIT = BuildData.COMMIT; + public static final String REPOSITORY = BuildData.REPOSITORY; /** * Oauth client ID for Microsoft authentication diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 784f30053..5a9b7888e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -42,7 +42,7 @@ architectury-plugin = "3.4-SNAPSHOT" architectury-loom = "1.6-SNAPSHOT" minotaur = "2.8.7" lombok = "8.4" -blossom = "1.2.0" +blossom = "2.1.0" [libraries] base-api = { group = "org.geysermc.api", name = "base-api", version.ref = "base-api" } From f49acb2f7c2281137837259af86e7db18845165d Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Thu, 20 Jun 2024 15:08:49 -0400 Subject: [PATCH 123/233] Indicate support for Bedrock 1.21.1 --- README.md | 2 +- .../main/java/org/geysermc/geyser/network/GameProtocol.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c45af73ed..e3b5a496a 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.80 - 1.21.0 and Minecraft Java 1.21 +### Currently supporting Minecraft Bedrock 1.20.80 - 1.21.1 and Minecraft Java 1.21 ## 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 773f0ae32..de995301a 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -48,7 +48,7 @@ public final class GameProtocol { * release of the game that Geyser supports. */ public static final BedrockCodec DEFAULT_BEDROCK_CODEC = CodecProcessor.processCodec(Bedrock_v685.CODEC.toBuilder() - .minecraftVersion("1.21.0") + .minecraftVersion("1.21.1") .build()); /** @@ -67,7 +67,7 @@ public final class GameProtocol { .minecraftVersion("1.20.80/1.20.81") .build())); SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(DEFAULT_BEDROCK_CODEC.toBuilder() - .minecraftVersion("1.21.0") + .minecraftVersion("1.21.0/1.20.1") .build())); } From dd9d5f321bfa878d1559ed6ef4ba39511d644e72 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Thu, 20 Jun 2024 15:24:39 -0400 Subject: [PATCH 124/233] Work around Bedrock players looking like Steve --- .../java/org/geysermc/geyser/skin/SkinManager.java | 11 +++++++++++ .../java/org/geysermc/geyser/skin/SkinProvider.java | 7 +++---- 2 files changed, 14 insertions(+), 4 deletions(-) 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 7b126c136..4c3db7504 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/SkinManager.java +++ b/core/src/main/java/org/geysermc/geyser/skin/SkinManager.java @@ -309,6 +309,15 @@ public class SkinManager { return null; } + if (DEFAULT_FLOODGATE_STEVE.equals(skinUrl)) { + // https://github.com/GeyserMC/Floodgate/commit/00b8b1b6364116ff4bc9b00e2015ce35bae8abb1 ensures that + // Bedrock players on online-mode servers will always have a textures property. However, this skin is + // also sent our way, and isn't overwritten. It's very likely that this skin is *only* a placeholder, + // and no one should ever be using it outside of Floodgate, and therefore no one wants to see this + // specific Steve skin. + return null; + } + boolean isAlex = skinTexture.has("metadata"); String capeUrl = null; @@ -322,5 +331,7 @@ public class SkinManager { return new GameProfileData(skinUrl, capeUrl, isAlex); } + + private static final String DEFAULT_FLOODGATE_STEVE = "https://textures.minecraft.net/texture/31f477eb1a7beee631c2ca64d06f8f68fa93a3386d04452ab27f43acdf1b60cb"; } } \ No newline at end of file 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 5b16bc3a3..aec1fa4de 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java +++ b/core/src/main/java/org/geysermc/geyser/skin/SkinProvider.java @@ -29,9 +29,6 @@ import com.fasterxml.jackson.databind.JsonNode; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; 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; @@ -56,7 +53,9 @@ import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.StandardCharsets; -import java.util.*; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; import java.util.concurrent.*; import java.util.function.Predicate; From 78642db3ad05f4f64c24f586c615c749b92871a6 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Thu, 20 Jun 2024 19:15:05 -0400 Subject: [PATCH 125/233] Ensure players get disconnected with no Java disconnect packet --- .../org/geysermc/geyser/session/GeyserSession.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 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 e228fc02f..7f015a05e 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -996,7 +996,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Override public void disconnected(DisconnectedEvent event) { loggingIn = false; - loggedIn = false; String disconnectMessage; Throwable cause = event.getCause(); @@ -1036,13 +1035,19 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { } 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); if (geyser.getConfig().isDebugMode()) { cause.printStackTrace(); } } + if ((!GeyserSession.this.closed && GeyserSession.this.loggedIn) || cause != null) { + // GeyserSession is disconnected via session.disconnect() called indirectly be the server + // This needs to be "initiated" here when there is an exception, but also when the Netty connection + // is closed without a disconnect packet - in this case, closed will still be false, but loggedIn + // will also be true as GeyserSession#disconnect will not have been called. + GeyserSession.this.disconnect(disconnectMessage); + } + + loggedIn = false; } @Override From c00a02e5eae445f16f97043156fe7fcd0203e02d Mon Sep 17 00:00:00 2001 From: basaigh <53559772+basaigh@users.noreply.github.com> Date: Fri, 21 Jun 2024 15:36:55 +0100 Subject: [PATCH 126/233] Add trial chambers map icon (#4783) --- .../main/java/org/geysermc/geyser/level/BedrockMapIcon.java | 3 ++- 1 file changed, 2 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 c55a74cd2..eacf6bd1b 100644 --- a/core/src/main/java/org/geysermc/geyser/level/BedrockMapIcon.java +++ b/core/src/main/java/org/geysermc/geyser/level/BedrockMapIcon.java @@ -63,7 +63,8 @@ public enum BedrockMapIcon { 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); + ICON_SWAMP_HUT(MapIconType.SWAMP_HUT, 23), + ICON_TRIAL_CHAMBERS(MapIconType.TRIAL_CHAMBERS, 24); private static final BedrockMapIcon[] VALUES = values(); From 110470726a301f2d5f7162c3fe4804757f01bd11 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 21 Jun 2024 18:28:05 +0200 Subject: [PATCH 127/233] Fix: Bedrock players dying of fall damage, instead of falling in the void (#4704) * fix https://github.com/GeyserMC/Geyser/issues/4649 * add javadoc --- .../type/player/SessionPlayerEntity.java | 74 +++++++++++++++++++ .../player/BedrockMovePlayerTranslator.java | 59 ++++++++------- 2 files changed, 106 insertions(+), 27 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 31eb02984..45fea4d48 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 @@ -27,15 +27,18 @@ package org.geysermc.geyser.entity.type.player; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.Getter; +import lombok.Setter; 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; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; +import org.cloudburstmc.protocol.bedrock.packet.MovePlayerPacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; import org.geysermc.geyser.entity.attribute.GeyserAttributeType; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.network.GameProtocol; +import org.geysermc.geyser.level.BedrockDimension; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.AttributeUtils; import org.geysermc.geyser.util.DimensionUtils; @@ -69,6 +72,15 @@ public class SessionPlayerEntity extends PlayerEntity { private int lastAirSupply = getMaxAir(); + /** + * Determines if our position is currently out-of-sync with the Java server + * due to our workaround for the void floor + *

+ * Must be reset when dying, switching worlds, or being teleported out of the void + */ + @Getter @Setter + private boolean voidPositionDesynched; + public SessionPlayerEntity(GeyserSession session) { super(session, -1, 1, null, Vector3f.ZERO, Vector3f.ZERO, 0, 0, 0, null, null); @@ -87,10 +99,25 @@ public class SessionPlayerEntity extends PlayerEntity { @Override public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, float headYaw, boolean isOnGround) { + if (voidPositionDesynched) { + if (!isBelowVoidFloor()) { + voidPositionDesynched = false; // No need to fix our offset; we've been moved + } + } super.moveRelative(relX, relY, relZ, yaw, pitch, headYaw, isOnGround); session.getCollisionManager().updatePlayerBoundingBox(this.position.down(definition.offset())); } + @Override + public void moveAbsolute(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) { + if (voidPositionDesynched) { + if (!isBelowVoidFloor()) { + voidPositionDesynched = false; // No need to fix our offset; we've been moved + } + } + super.moveAbsolute(position, yaw, pitch, headYaw, isOnGround, teleported); + } + @Override public void setPosition(Vector3f position) { if (valid) { // Don't update during session init @@ -225,6 +252,9 @@ public class SessionPlayerEntity extends PlayerEntity { } else { dirtyMetadata.put(EntityDataTypes.PLAYER_HAS_DIED, false); } + + // We're either respawning or switching worlds, either way, we are no longer desynched + this.setVoidPositionDesynched(false); } @Override @@ -276,4 +306,48 @@ public class SessionPlayerEntity extends PlayerEntity { public void resetAir() { this.setAirSupply(getMaxAir()); } + + private boolean isBelowVoidFloor() { + return position.getY() < voidFloorPosition(); + } + + public int voidFloorPosition() { + // The void floor is offset about 40 blocks below the bottom of the world + BedrockDimension bedrockDimension = session.getChunkCache().getBedrockDimension(); + return bedrockDimension.minY() - 40; + } + + /** + * This method handles teleporting the player below or above the Bedrock void floor. + * The Java server should never see this desync as we adjust the position that we send to it + * + * @param up in which direction to teleport - true to resync our position, or false to be + * teleported below the void floor. + */ + public void teleportVoidFloorFix(boolean up) { + // Safety to avoid double teleports + if ((voidPositionDesynched && !up) || (!voidPositionDesynched && up)) { + return; + } + + // Work around there being a floor at the bottom of the world and teleport the player below it + // Moving from below to above the void floor works fine + Vector3f newPosition = this.getPosition(); + if (up) { + newPosition = newPosition.up(4f); + voidPositionDesynched = false; + } else { + newPosition = newPosition.down(4f); + voidPositionDesynched = true; + } + + this.setPositionManual(newPosition); + MovePlayerPacket movePlayerPacket = new MovePlayerPacket(); + movePlayerPacket.setRuntimeEntityId(geyserId); + movePlayerPacket.setPosition(newPosition); + movePlayerPacket.setRotation(getBedrockRotation()); + movePlayerPacket.setMode(MovePlayerPacket.Mode.TELEPORT); + movePlayerPacket.setTeleportationCause(MovePlayerPacket.TeleportationCause.BEHAVIOR); + session.sendUpstreamPacketImmediately(movePlayerPacket); + } } 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 cae12170d..3d612c481 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,20 +25,19 @@ package org.geysermc.geyser.translator.protocol.bedrock.entity.player; -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; import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.type.player.SessionPlayerEntity; -import org.geysermc.geyser.level.BedrockDimension; 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.mcprotocollib.network.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; @Translator(packet = MovePlayerPacket.class) public class BedrockMovePlayerTranslator extends PacketTranslator { @@ -93,29 +92,42 @@ public class BedrockMovePlayerTranslator extends PacketTranslator= packet.getPosition().getY()) { + if (entity.getPosition().getY() >= packet.getPosition().getY() && !isBelowVoid) { int floorY = position.getFloorY(); - // The void floor is offset about 40 blocks below the bottom of the world - BedrockDimension bedrockDimension = session.getChunkCache().getBedrockDimension(); - int voidFloorLocation = bedrockDimension.minY() - 40; - teleportThroughVoidFloor = floorY <= (voidFloorLocation + 2) && floorY >= voidFloorLocation; - if (teleportThroughVoidFloor) { - // https://github.com/GeyserMC/Geyser/issues/3521 - no void floor in Java so we cannot be on the ground. - onGround = false; - } + int voidFloorLocation = entity.voidFloorPosition(); + teleportThroughVoidFloor = floorY <= (voidFloorLocation + 1) && floorY >= voidFloorLocation; } else { teleportThroughVoidFloor = false; } + if (teleportThroughVoidFloor || isBelowVoid) { + // https://github.com/GeyserMC/Geyser/issues/3521 - no void floor in Java so we cannot be on the ground. + onGround = false; + } + + if (isBelowVoid) { + int floorY = position.getFloorY(); + int voidFloorLocation = entity.voidFloorPosition(); + mustResyncPosition = floorY < voidFloorLocation && floorY >= voidFloorLocation - 1; + } else { + mustResyncPosition = false; + } + + double yPosition = position.getY(); + if (entity.isVoidPositionDesynched()) { // not using the cached variable on purpose + yPosition += 4; // We are de-synched since we had to teleport below the void floor. + } + Packet movePacket; if (rotationChanged) { // Send rotation updates as well movePacket = new ServerboundMovePlayerPosRotPacket( onGround, - position.getX(), position.getY(), position.getZ(), + position.getX(), yPosition, position.getZ(), yaw, pitch ); entity.setYaw(yaw); @@ -123,7 +135,7 @@ public class BedrockMovePlayerTranslator extends PacketTranslator Date: Fri, 21 Jun 2024 13:50:10 -0400 Subject: [PATCH 128/233] Show trial chamber map item texture --- .../main/java/org/geysermc/geyser/item/type/FilledMapItem.java | 1 + 1 file changed, 1 insertion(+) 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 70a04b863..e571a796a 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 @@ -51,6 +51,7 @@ public class FilledMapItem extends MapItem { switch (mapColor) { case 3830373 -> builder.damage(3); // Ocean Monument case 5393476 -> builder.damage(4); // Woodland explorer + case 12741452 -> builder.damage(14); // Trial Chamber } } } From 21ccafc40c3d389b734ade256b7bd8acafab1f2c Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Fri, 21 Jun 2024 13:53:38 -0400 Subject: [PATCH 129/233] DataComponentType.ITEM_NAME should remove italics --- .../geyser/translator/item/ItemTranslator.java | 10 ++++++---- 1 file changed, 6 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 a8d29c465..85b4c6264 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 @@ -418,13 +418,15 @@ public final class ItemTranslator { 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 return MessageTranslator.convertMessage(customName, session.locale()); } + customName = components.get(DataComponentType.ITEM_NAME); + if (customName != null) { + // Get the translated name and prefix it with a reset char to prevent italics - matches Java Edition + // behavior as of 1.21 + return ChatColor.RESET + ChatColor.ESCAPE + translationColor + MessageTranslator.convertMessage(customName, session.locale()); + } } if (mapping.hasTranslation()) { From e6bf3ffdf04eeecb36ad385da690b4d539c58cae Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Fri, 21 Jun 2024 15:58:23 -0400 Subject: [PATCH 130/233] Proper trial spawner block entity data --- .../geyser/entity/EntityDefinition.java | 1 + .../entity/SpawnerBlockEntityTranslator.java | 2 +- .../TrialSpawnerBlockEntityTranslator.java | 19 ++++++++++++++----- 3 files changed, 16 insertions(+), 6 deletions(-) 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 31aa7cc73..f9b65a545 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinition.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinition.java @@ -47,6 +47,7 @@ import java.util.function.BiConsumer; * metadata translators needed to translate the properties sent from the server. The translators are structured in such * a way that inserting a new one (for example in version updates) is convenient. * + * @param identifier the Bedrock identifier of this entity * @param the entity type this definition represents */ public record EntityDefinition(EntityFactory factory, EntityType entityType, String identifier, 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 6b26f2b2c..14f706f27 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 @@ -107,7 +107,7 @@ public class SpawnerBlockEntityTranslator extends BlockEntityTranslator { bedrockNbt.put("isMovable", (byte) 1); } - static void translateSpawnData(@NonNull NbtMapBuilder builder, @Nullable NbtMap spawnData) { + private static void translateSpawnData(@NonNull NbtMapBuilder builder, @Nullable NbtMap spawnData) { if (spawnData == null) { return; } 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 dd58bfa6f..25925a89b 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 @@ -27,22 +27,31 @@ package org.geysermc.geyser.translator.level.block.entity; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; +import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.level.block.type.BlockState; +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.TRIAL_SPAWNER) public class TrialSpawnerBlockEntityTranslator extends BlockEntityTranslator { + // Note that it would appear block entity updates don't include the NBT, but we do need it on chunk load. @Override public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) { if (javaNbt == null) { return; } - // trial spawners have "spawn_data" instead of "SpawnData" - SpawnerBlockEntityTranslator.translateSpawnData(bedrockNbt, javaNbt.getCompound("spawn_data", null)); - - // Because trial spawners don't exist on bedrock yet - bedrockNbt.put("id", "MobSpawner"); + NbtMap entityData = javaNbt.getCompound("spawn_data").getCompound("entity"); + if (entityData.isEmpty()) { + return; + } + NbtMapBuilder spawnData = NbtMap.builder(); + EntityDefinition definition = Registries.JAVA_ENTITY_IDENTIFIERS.get(entityData.getString("id")); + if (definition != null) { + spawnData.putString("TypeId", definition.identifier()); + } + spawnData.putInt("Weight", entityData.getInt("Size", 1)); // ??? presumably since these are the only other two extra attributes + bedrockNbt.putCompound("spawn_data", spawnData.build()); } } From 55e90b6f576877ab24f65ab874de90c2da803cca Mon Sep 17 00:00:00 2001 From: chris Date: Sat, 22 Jun 2024 20:32:29 +0200 Subject: [PATCH 131/233] Show build number in startup log, fix Geyser version command(#4336) * Version check command/startup log shows build number * Add development build warning * Fix `/geyser version` command * Hack around outdated language module --- core/build.gradle.kts | 24 ++++++--- .../org/geysermc/geyser/BuildData.java | 5 ++ .../java/org/geysermc/geyser/GeyserImpl.java | 8 +++ .../command/defaults/VersionCommand.java | 54 +++++++++++-------- 4 files changed, 60 insertions(+), 31 deletions(-) diff --git a/core/build.gradle.kts b/core/build.gradle.kts index e7b63ff56..fe2576462 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -75,7 +75,7 @@ tasks.processResources { expand( "branch" to info.branch, "buildNumber" to info.buildNumber, - "projectVersion" to project.version, + "projectVersion" to info.version, "commit" to info.commit, "commitAbbrev" to info.commitAbbrev, "commitMessage" to info.commitMessage, @@ -89,20 +89,25 @@ sourceSets { blossom { val info = GitInfo() javaSources { - property("version", "${project.version} (${info.gitVersion})") + property("version", "${info.version} (${info.gitVersion})") property("gitVersion", info.gitVersion) property("buildNumber", info.buildNumber.toString()) property("branch", info.branch) property("commit", info.commit) property("repository", info.repository) + property("devVersion", info.isDev.toString()) } } } } -fun Project.buildNumber(): Int = +fun buildNumber(): Int = (System.getenv("BUILD_NUMBER"))?.let { Integer.parseInt(it) } ?: -1 +fun isDevBuild(branch: String, repository: String): Boolean { + return branch != "master" || repository.equals("https://github.com/GeyserMC/Geyser", ignoreCase = true).not() +} + inner class GitInfo { val branch: String val commit: String @@ -115,22 +120,25 @@ inner class GitInfo { val commitMessage: String val repository: String + val isDev: Boolean + init { - // On Jenkins, a detached head is checked out, so indra cannot determine the branch. - // Fortunately, this environment variable is available. - branch = indraGit.branchName() ?: System.getenv("BRANCH_NAME") ?: "DEV" + branch = indraGit.branchName() ?: "DEV" val commit = indraGit.commit() this.commit = commit?.name ?: "0".repeat(40) commitAbbrev = commit?.name?.substring(0, 7) ?: "0".repeat(7) gitVersion = "git-${branch}-${commitAbbrev}" - version = "${project.version} ($gitVersion)" - buildNumber = buildNumber() val git = indraGit.git() commitMessage = git?.commit()?.message ?: "" repository = git?.repository?.config?.getString("remote", "origin", "url") ?: "" + + buildNumber = buildNumber() + isDev = isDevBuild(branch, repository) + val projectVersion = if (isDev) project.version else project.version.toString().replace("SNAPSHOT", "b${buildNumber}") + version = "$projectVersion ($gitVersion)" } } diff --git a/core/src/main/java-templates/org/geysermc/geyser/BuildData.java b/core/src/main/java-templates/org/geysermc/geyser/BuildData.java index d489d8d17..0e4d08bfe 100644 --- a/core/src/main/java-templates/org/geysermc/geyser/BuildData.java +++ b/core/src/main/java-templates/org/geysermc/geyser/BuildData.java @@ -34,4 +34,9 @@ public class BuildData { public static final String BRANCH = "{{ branch }}"; public static final String COMMIT = "{{ commit }}"; public static final String REPOSITORY = "{{ repository }}"; + private static final String DEV = "{{ devVersion }}"; + + public static boolean isDevBuild() { + return Boolean.parseBoolean(DEV); + } } diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 0975ea5a9..a3eeca6a5 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -122,6 +122,7 @@ public class GeyserImpl implements GeyserApi { public static final String BRANCH = BuildData.BRANCH; public static final String COMMIT = BuildData.COMMIT; public static final String REPOSITORY = BuildData.REPOSITORY; + public static final boolean IS_DEV = BuildData.isDevBuild(); /** * Oauth client ID for Microsoft authentication @@ -207,6 +208,12 @@ public class GeyserImpl implements GeyserApi { logger.info(""); logger.info(GeyserLocale.getLocaleStringLog("geyser.core.load", NAME, VERSION)); logger.info(""); + if (IS_DEV) { + // TODO cloud use language string + //logger.info(GeyserLocale.getLocaleStringLog("geyser.core.dev_build", "https://discord.gg/geysermc")); + logger.info("You are running a development build of Geyser! Please report any bugs you find on our Discord server: %s".formatted("https://discord.gg/geysermc")); + logger.info(""); + } logger.info("******************************************"); /* Initialize registries */ @@ -684,6 +691,7 @@ public class GeyserImpl implements GeyserApi { * * @return true if the version number is not 'DEV'. */ + @SuppressWarnings("BooleanMethodIsAlwaysInverted") public boolean isProductionEnvironment() { // First is if Blossom runs, second is if Blossom doesn't run //noinspection ConstantConditions,MismatchedStringCase - changes in production 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 eb2e8ff47..c6852d577 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 @@ -25,8 +25,8 @@ package org.geysermc.geyser.command.defaults; +import com.fasterxml.jackson.databind.JsonNode; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; -import org.geysermc.geyser.Constants; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.command.GeyserCommand; @@ -37,8 +37,7 @@ import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.util.WebUtils; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; +import java.io.IOException; import java.util.List; public class VersionCommand extends GeyserCommand { @@ -72,27 +71,36 @@ public class VersionCommand extends GeyserCommand { GeyserImpl.NAME, GeyserImpl.VERSION, javaVersions, bedrockVersions)); // Disable update checking in dev mode and for players in Geyser Standalone - if (GeyserImpl.getInstance().isProductionEnvironment() && !(!sender.isConsole() && geyser.getPlatformType() == PlatformType.STANDALONE)) { - 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) + "/lastSuccessfulBuild/api/xml?xpath=//buildNumber"); - if (buildXML.startsWith("")) { - int latestBuildNum = Integer.parseInt(buildXML.replaceAll("<(\\\\)?(/)?buildNumber>", "").trim()); - int buildNum = this.geyser.buildNumber(); - if (latestBuildNum == buildNum) { - sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.version.no_updates", sender.locale())); - } else { - sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.version.outdated", - sender.locale(), (latestBuildNum - buildNum), Constants.GEYSER_DOWNLOAD_LOCATION)); - } - } else { - throw new AssertionError("buildNumber missing"); - } - } 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())); + if (!GeyserImpl.getInstance().isProductionEnvironment() || (!sender.isConsole() && geyser.getPlatformType() == PlatformType.STANDALONE)) { + return; + } + + if (GeyserImpl.IS_DEV) { + // TODO cloud use language string + sender.sendMessage("You are running a development build of Geyser! Please report any bugs you find on our Discord server: %s" + .formatted("https://discord.gg/geysermc")); + //sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.core.dev_build", sender.locale(), "https://discord.gg/geysermc")); + return; + } + + sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.version.checking", sender.locale())); + try { + int buildNumber = this.geyser.buildNumber(); + JsonNode response = WebUtils.getJson("https://download.geysermc.org/v2/projects/geyser/versions/latest/builds/latest"); + int latestBuildNumber = response.get("build").asInt(); + + if (latestBuildNumber == buildNumber) { + sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.version.no_updates", sender.locale())); + return; } + + sender.sendMessage(GeyserLocale.getPlayerLocaleString( + "geyser.commands.version.outdated", + sender.locale(), (latestBuildNumber - buildNumber), "https://geysermc.org/download" + )); + } catch (IOException e) { + GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.commands.version.failed"), e); + sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.commands.version.failed", sender.locale())); } } From a8bd93a075b17bd7d008465ba47353a086869ce8 Mon Sep 17 00:00:00 2001 From: Ethan <68365423+letsgoawaydev@users.noreply.github.com> Date: Mon, 24 Jun 2024 03:43:09 +0800 Subject: [PATCH 132/233] Add fix (#4792) --- .../org/geysermc/geyser/entity/type/PaintingEntity.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 6d0294783..09c055c84 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 @@ -86,7 +86,11 @@ public class PaintingEntity extends Entity { private Vector3f fixOffset(PaintingType paintingName) { Vector3f position = super.position; - position = position.add(0.5, 0.5, 0.5); + // ViaVersion already adds the offset for us on older versions, + // so no need to do it then otherwise it will be spaced + if (session.isEmulatePost1_18Logic()) { + position = position.add(0.5, 0.5, 0.5); + } double widthOffset = paintingName.getWidth() > 1 && paintingName.getWidth() != 3 ? 0.5 : 0; double heightOffset = paintingName.getHeight() > 1 && paintingName.getHeight() != 3 ? 0.5 : 0; From ca2312c7f68c54f32314c40c2c1db5d9cda5a0b2 Mon Sep 17 00:00:00 2001 From: Alex <40795980+AlexProgrammerDE@users.noreply.github.com> Date: Mon, 24 Jun 2024 19:45:30 +0200 Subject: [PATCH 133/233] Create .editorconfig (#4615) --- .editorconfig | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..c32bad0c8 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +root = true + +[*] +charset = utf-8 +indent_size = 4 +indent_style = space +insert_final_newline = true +tab_width = 4 +max_line_length = off + +[*.java] +ij_java_class_count_to_use_import_on_demand = 9999 +ij_java_doc_align_exception_comments = false +ij_java_doc_align_param_comments = false From 835ba9e24f5904ab5ee84f574a94e6a5a637a3df Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Mon, 24 Jun 2024 16:25:12 -0400 Subject: [PATCH 134/233] Remove casting from block mappings --- .../java/org/geysermc/geyser/registry/type/BlockMappings.java | 4 ++-- .../main/java/org/geysermc/geyser/session/GeyserSession.java | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) 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 5c4e835e4..be96fec0e 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 @@ -44,7 +44,7 @@ import java.util.Set; @Builder @Value -public class BlockMappings implements DefinitionRegistry { +public class BlockMappings implements DefinitionRegistry { GeyserBedrockBlock bedrockAir; BlockDefinition bedrockWater; BlockDefinition bedrockMovingBlock; @@ -134,7 +134,7 @@ public class BlockMappings implements DefinitionRegistry { } @Override - public boolean isRegistered(GeyserBedrockBlock bedrockBlock) { + public boolean isRegistered(BlockDefinition bedrockBlock) { return getDefinition(bedrockBlock.getRuntimeId()) == bedrockBlock; } } \ No newline at end of file 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 7f015a05e..25dd21662 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -57,7 +57,6 @@ 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; import org.geysermc.api.util.BedrockPlatform; import org.geysermc.api.util.InputMode; @@ -1466,7 +1465,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().setBlockDefinitions(this.blockMappings); this.upstream.getCodecHelper().setCameraPresetDefinitions(CameraDefinitions.CAMERA_DEFINITIONS); StartGamePacket startGamePacket = new StartGamePacket(); From 130b27203f8b7214c986f13b103e9398f2f7b9ad Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Fri, 28 Jun 2024 22:55:36 -0400 Subject: [PATCH 135/233] Limit particle amount in LevelParticlesPacket (#4802) --- .../protocol/java/level/JavaLevelParticlesTranslator.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 83b5da219..9ec6ee51e 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 @@ -60,6 +60,7 @@ import java.util.function.Function; @Translator(packet = ClientboundLevelParticlesPacket.class) public class JavaLevelParticlesTranslator extends PacketTranslator { + private static final int MAX_PARTICLES = 100; @Override public void translate(GeyserSession session, ClientboundLevelParticlesPacket packet) { @@ -71,7 +72,8 @@ public class JavaLevelParticlesTranslator extends PacketTranslator Date: Sat, 29 Jun 2024 13:32:00 -0400 Subject: [PATCH 136/233] Update license to 2024 --- .github/workflows/build.yml | 1 - LICENSE | 2 +- licenseheader.txt | 24 ------------------------ 3 files changed, 1 insertion(+), 26 deletions(-) delete mode 100644 licenseheader.txt diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2bcf25e8e..59aa89086 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,7 +16,6 @@ on: - 'LICENSE' - 'Jenkinsfile ' - 'README.md' - - 'licenseheader.txt' jobs: build: diff --git a/LICENSE b/LICENSE index bde252698..ba3a723ff 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -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 diff --git a/licenseheader.txt b/licenseheader.txt deleted file mode 100644 index 9bfe117f9..000000000 --- a/licenseheader.txt +++ /dev/null @@ -1,24 +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 - */ \ No newline at end of file From 76126869721457b921ed25c2acf3523a543a6173 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sun, 30 Jun 2024 22:03:30 -0400 Subject: [PATCH 137/233] Don't show git version string twice --- core/build.gradle.kts | 4 ++-- core/src/main/java/org/geysermc/geyser/GeyserImpl.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/build.gradle.kts b/core/build.gradle.kts index fe2576462..1d1794cf7 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -89,7 +89,7 @@ sourceSets { blossom { val info = GitInfo() javaSources { - property("version", "${info.version} (${info.gitVersion})") + property("version", info.version) property("gitVersion", info.gitVersion) property("buildNumber", info.buildNumber.toString()) property("branch", info.branch) @@ -156,4 +156,4 @@ tasks.register("downloadBedrockData") { 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/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index a3eeca6a5..88cc74691 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -694,7 +694,7 @@ public class GeyserImpl implements GeyserApi { @SuppressWarnings("BooleanMethodIsAlwaysInverted") public boolean isProductionEnvironment() { // First is if Blossom runs, second is if Blossom doesn't run - //noinspection ConstantConditions,MismatchedStringCase - changes in production + //noinspection ConstantConditions - changes in production return !("git-local/dev-0000000".equals(GeyserImpl.GIT_VERSION) || "${gitVersion}".equals(GeyserImpl.GIT_VERSION)); } From 48ea81eb9845b621e2bb1434669a2e2a51eded43 Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 1 Jul 2024 17:17:52 +0200 Subject: [PATCH 138/233] Update mappings (#4812) Fixes short grass mapping --- 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 23cb22f9c..69e302bf3 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 23cb22f9ceeb7f24b896a69a711944d7f3e756ed +Subproject commit 69e302bf3a118e5274f86b23a1818c61dba84c64 From ff1e1dd7e38f617454b1b439d3056361072b795b Mon Sep 17 00:00:00 2001 From: Eclipse <116838833+eclipseisoffline@users.noreply.github.com> Date: Tue, 2 Jul 2024 13:17:47 +0000 Subject: [PATCH 139/233] Fix attribute modifier tooltips (#4816) --- .../geysermc/geyser/translator/item/ItemTranslator.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 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 85b4c6264..abe39f177 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 @@ -52,6 +52,7 @@ 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.entity.attribute.AttributeType; 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.*; @@ -209,7 +210,7 @@ public final class ItemTranslator { Map> slotsToModifiers = new HashMap<>(); for (ItemAttributeModifiers.Entry entry : modifiers.getModifiers()) { // convert the modifier tag to a lore entry - String loreEntry = attributeToLore(entry.getModifier(), language); + String loreEntry = attributeToLore(entry.getAttribute(), entry.getModifier(), language); if (loreEntry == null) { continue; // invalid or failed } @@ -254,13 +255,13 @@ public final class ItemTranslator { } @Nullable - private static String attributeToLore(ItemAttributeModifiers.AttributeModifier modifier, String language) { + private static String attributeToLore(int attribute, ItemAttributeModifiers.AttributeModifier modifier, String language) { double amount = modifier.getAmount(); if (amount == 0) { return null; } - String name = modifier.getId().asMinimalString(); + String name = AttributeType.Builtin.from(attribute).getIdentifier().asMinimalString(); // the namespace does not need to be present, but if it is, the java client ignores it as of pre-1.20.5 ModifierOperation operation = modifier.getOperation(); From 9f19c0a9f614d9e40141fb490163aa3ca2d66cd2 Mon Sep 17 00:00:00 2001 From: Ethan <68365423+letsgoawaydev@users.noreply.github.com> Date: Sat, 6 Jul 2024 17:58:54 +0800 Subject: [PATCH 140/233] Fix: Trial Spawner Level Events (#4821) * commit every thing i could do, couldnt get it to work with ominous stuff * Fix trial spawner events to work correctly. * Update mappings to latest * fix comment * Workaround for buggy trial chamber particles * Fix positioning and also fix become ominous event * Fix sounds and positioning again * Fix random new line * Update mappings * update cloudburst library to 20240704.153116-14 * Fix accidental random line --- .../java/level/JavaLevelEventTranslator.java | 134 +++++++++++++++--- core/src/main/resources/mappings | 2 +- gradle/libs.versions.toml | 2 +- 3 files changed, 116 insertions(+), 22 deletions(-) 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 d4e317af4..542af1598 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 @@ -28,9 +28,16 @@ package org.geysermc.geyser.translator.protocol.java.level; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.protocol.bedrock.data.LevelEvent; import org.cloudburstmc.protocol.bedrock.data.ParticleType; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; -import org.cloudburstmc.protocol.bedrock.packet.*; +import org.cloudburstmc.protocol.bedrock.packet.LevelEventGenericPacket; +import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; +import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket; +import org.cloudburstmc.protocol.bedrock.packet.PlaySoundPacket; +import org.cloudburstmc.protocol.bedrock.packet.SpawnParticleEffectPacket; +import org.cloudburstmc.protocol.bedrock.packet.StopSoundPacket; +import org.cloudburstmc.protocol.bedrock.packet.TextPacket; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.level.JukeboxSong; import org.geysermc.geyser.registry.Registries; @@ -40,13 +47,27 @@ import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.translator.level.event.LevelEventTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; +import org.geysermc.geyser.util.DimensionUtils; import org.geysermc.geyser.util.SoundUtils; import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction; -import org.geysermc.mcprotocollib.protocol.data.game.level.event.*; +import org.geysermc.mcprotocollib.protocol.data.game.level.event.BonemealGrowEventData; +import org.geysermc.mcprotocollib.protocol.data.game.level.event.BreakBlockEventData; +import org.geysermc.mcprotocollib.protocol.data.game.level.event.BreakPotionEventData; +import org.geysermc.mcprotocollib.protocol.data.game.level.event.ComposterEventData; +import org.geysermc.mcprotocollib.protocol.data.game.level.event.DragonFireballEventData; +import org.geysermc.mcprotocollib.protocol.data.game.level.event.LevelEventType; +import org.geysermc.mcprotocollib.protocol.data.game.level.event.RecordEventData; +import org.geysermc.mcprotocollib.protocol.data.game.level.event.SculkBlockChargeEventData; +import org.geysermc.mcprotocollib.protocol.data.game.level.event.SmokeEventData; +import org.geysermc.mcprotocollib.protocol.data.game.level.event.TrialSpawnerDetectEventData; +import org.geysermc.mcprotocollib.protocol.data.game.level.event.UnknownLevelEventData; import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundLevelEventPacket; import java.util.Collections; +import java.util.Optional; +import java.util.Random; import java.util.Set; +import java.util.concurrent.ThreadLocalRandom; @Translator(packet = ClientboundLevelEventPacket.class) public class JavaLevelEventTranslator extends PacketTranslator { @@ -291,6 +312,20 @@ public class JavaLevelEventTranslator extends PacketTranslator effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.ANIMATION_SPAWN_COBWEB); + case ANIMATION_VAULT_ACTIVATE -> effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.ANIMATION_VAULT_ACTIVATE); + case ANIMATION_VAULT_DEACTIVATE -> effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.ANIMATION_VAULT_DEACTIVATE); + case ANIMATION_VAULT_EJECT_ITEM -> effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.ANIMATION_VAULT_EJECT_ITEM); + case ANIMATION_TRIAL_SPAWNER_EJECT_ITEM -> { + Random random = ThreadLocalRandom.current(); + PlaySoundPacket playSoundPacket = new PlaySoundPacket(); + playSoundPacket.setSound("trial_spawner.eject_item"); + playSoundPacket.setPosition(pos); + playSoundPacket.setVolume(1.0f); + playSoundPacket.setPitch(0.8f + random.nextFloat() * 0.3f); + session.sendUpstreamPacket(playSoundPacket); + return; + } case DRIPSTONE_DRIP -> effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_DRIPSTONE_DRIP); case PARTICLES_ELECTRIC_SPARK -> effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_ELECTRIC_SPARK); // Matches with a Bedrock server but doesn't seem to match up with Java case PARTICLES_AND_SOUND_WAX_ON -> effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_WAX_ON); @@ -303,22 +338,22 @@ public class JavaLevelEventTranslator extends PacketTranslator 0) { levelEventPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.SCULK_CHARGE); levelEventPacket.setTag( - NbtMap.builder() - .putInt("x", packet.getPosition().getX()) - .putInt("y", packet.getPosition().getY()) - .putInt("z", packet.getPosition().getZ()) - .putShort("charge", (short) eventData.getCharge()) - .putShort("facing", encodeFacing(eventData.getBlockFaces())) // TODO check if this is actually correct - .build() + NbtMap.builder() + .putInt("x", packet.getPosition().getX()) + .putInt("y", packet.getPosition().getY()) + .putInt("z", packet.getPosition().getZ()) + .putShort("charge", (short) eventData.getCharge()) + .putShort("facing", encodeFacing(eventData.getBlockFaces())) // TODO check if this is actually correct + .build() ); } else { levelEventPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.SCULK_CHARGE_POP); levelEventPacket.setTag( - NbtMap.builder() - .putInt("x", packet.getPosition().getX()) - .putInt("y", packet.getPosition().getY()) - .putInt("z", packet.getPosition().getZ()) - .build() + NbtMap.builder() + .putInt("x", packet.getPosition().getX()) + .putInt("y", packet.getPosition().getY()) + .putInt("z", packet.getPosition().getZ()) + .build() ); } session.sendUpstreamPacket(levelEventPacket); @@ -328,11 +363,11 @@ public class JavaLevelEventTranslator extends PacketTranslator { + // Particles spawn here + TrialSpawnerDetectEventData eventData = (TrialSpawnerDetectEventData) packet.getData(); + effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_TRIAL_SPAWNER_DETECTION); + // 0.75 is used here for Y instead of 0.5 to match Java Positioning. + // 0.5 is what the BDS uses for positioning. + effectPacket.setPosition(pos.sub(0.5f, 0.75f, 0.5f)); + effectPacket.setData(eventData.getDetectedPlayers()); + } + case PARTICLES_TRIAL_SPAWNER_DETECT_PLAYER_OMINOUS -> { + effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_TRIAL_SPAWNER_DETECTION_CHARGED); + effectPacket.setPosition(pos.sub(0.5f, 0.75f, 0.5f)); + /* + Particles don't spawn here for some reason, only sound plays + This seems to be a bug in v1.21.0 and v1.21.1: see https://bugs.mojang.com/browse/MCPE-181465 + If this gets fixed, the spawnOminousTrialSpawnerParticles function can be removed. + The positioning should be the same as normal activation. + */ + spawnOminousTrialSpawnerParticles(session, pos); + } + case PARTICLES_TRIAL_SPAWNER_BECOME_OMINOUS -> { + effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_TRIAL_SPAWNER_BECOME_CHARGED); + effectPacket.setPosition(pos.sub(0.5f, 0.5f, 0.5f)); + // Same issue as above here + spawnOminousTrialSpawnerParticles(session, pos); + } + case PARTICLES_TRIAL_SPAWNER_SPAWN_MOB_AT -> { + // This should be its own class in MCProtocolLib. + // if 0, use Orange Flames, + // if 1, use Blue Flames for ominous spawners + UnknownLevelEventData eventData = (UnknownLevelEventData) packet.getData(); + effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_TRIAL_SPAWNER_SPAWNING); + effectPacket.setData(eventData.getData()); + } + case PARTICLES_TRIAL_SPAWNER_SPAWN -> { + UnknownLevelEventData eventData = (UnknownLevelEventData) packet.getData(); + effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_TRIAL_SPAWNER_SPAWNING); + effectPacket.setData(eventData.getData()); + + Random random = ThreadLocalRandom.current(); + PlaySoundPacket playSoundPacket = new PlaySoundPacket(); + playSoundPacket.setSound("trial_spawner.spawn_mob"); + playSoundPacket.setPosition(pos); + playSoundPacket.setVolume(1.0f); + playSoundPacket.setPitch(0.8f + random.nextFloat() * 0.3f); + session.sendUpstreamPacket(playSoundPacket); + } + case PARTICLES_TRIAL_SPAWNER_SPAWN_ITEM -> effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_TRIAL_SPAWNER_EJECTING); case SOUND_STOP_JUKEBOX_SONG -> { String bedrockSound = session.getWorldCache().removeActiveRecord(origin); if (bedrockSound == null) { @@ -396,4 +479,15 @@ public class JavaLevelEventTranslator extends PacketTranslator Date: Sat, 6 Jul 2024 21:50:19 +0800 Subject: [PATCH 141/233] Fix toggleable block opening sounds (doors, trapdoors, fence gates) (#4815) * Initial Commit * Fix minor copy and paste comment mistake * Remove debug log Co-authored-by: chris * Remove iron check on fence gate sound translator iron fence gates dont exist lol * Remove iron check from fence gate sound translator. Iron fence gates dont exist (yet) * Remove unnecessary curly braces * Rewrite the code, now functioning correctly with the runtime id * Update mappings * Better formatting Co-authored-by: chris * fix comment because it is referring to code that has been changed * Hopefully fix double closing * Seems like the double closing issue isnt from my code and from somewhere else * Fix issue where doors would update twice when opening/closing them using the upper half * change weird variable name --------- Co-authored-by: chris --- .../geyser/level/block/type/DoorBlock.java | 15 +++++++- .../java/level/JavaBlockUpdateTranslator.java | 4 +-- .../BlockSoundInteractionTranslator.java | 12 +++---- .../BucketSoundInteractionTranslator.java | 4 ++- .../ComparatorSoundInteractionTranslator.java | 4 ++- .../FlintAndSteelInteractionTranslator.java | 3 +- .../block/GrassPathInteractionTranslator.java | 4 ++- .../sound/block/HoeInteractionTranslator.java | 4 ++- .../LeverSoundInteractionTranslator.java | 4 ++- ...> OpenableSoundInteractionTranslator.java} | 35 +++++++++++++++---- .../org/geysermc/geyser/util/SoundUtils.java | 4 +-- 11 files changed, 69 insertions(+), 24 deletions(-) rename core/src/main/java/org/geysermc/geyser/translator/sound/block/{DoorSoundInteractionTranslator.java => OpenableSoundInteractionTranslator.java} (55%) diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/DoorBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/DoorBlock.java index bfde51a79..2efbdb523 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/DoorBlock.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/DoorBlock.java @@ -37,9 +37,22 @@ public class DoorBlock extends Block { @Override public void updateBlock(GeyserSession session, BlockState state, Vector3i position) { + // Needed to check whether we must force the client to update the door state. + String doubleBlockHalf = state.getValue(Properties.DOUBLE_BLOCK_HALF); + + if (doubleBlockHalf.equals("lower")) { + BlockState oldBlockState = session.getGeyser().getWorldManager().blockAt(session, position); + // If these are the same, it means that we already updated the lower door block (manually in the workaround below), + // and we do not need to update the block in the cache/on the client side using the super.updateBlock() method again. + // Otherwise, we send the door updates twice which will cause visual glitches on the client side + if (oldBlockState == state) { + return; + } + } + super.updateBlock(session, state, position); - if (state.getValue(Properties.DOUBLE_BLOCK_HALF).equals("upper")) { + if (doubleBlockHalf.equals("upper")) { // 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); 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 74b961996..d89775662 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 @@ -100,8 +100,8 @@ public class JavaBlockUpdateTranslator extends PacketTranslator { - +public interface BlockSoundInteractionTranslator extends SoundInteractionTranslator { /** * Handles the block interaction when a player * right-clicks a block. * * @param session the session interacting with the block * @param position the position of the block - * @param identifier the identifier of the block + * @param state the state of the block */ - static void handleBlockInteraction(GeyserSession session, Vector3f position, String identifier) { + static void handleBlockInteraction(GeyserSession session, Vector3f position, BlockState state) { // If we need to get the hand identifier, only get it once and save it to a variable String handIdentifier = null; @@ -58,7 +58,7 @@ public interface BlockSoundInteractionTranslator extends SoundInteractionTransla if (interactionEntry.getKey().blocks().length != 0) { boolean contains = false; for (String blockIdentifier : interactionEntry.getKey().blocks()) { - if (identifier.contains(blockIdentifier)) { + if (state.toString().contains(blockIdentifier)) { contains = true; break; } @@ -87,7 +87,7 @@ public interface BlockSoundInteractionTranslator extends SoundInteractionTransla continue; } } - ((BlockSoundInteractionTranslator) interactionEntry.getValue()).translate(session, position, identifier); + ((BlockSoundInteractionTranslator) interactionEntry.getValue()).translate(session, position, state); } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/sound/block/BucketSoundInteractionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/sound/block/BucketSoundInteractionTranslator.java index 7a5e86af7..45800e1ab 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/sound/block/BucketSoundInteractionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/sound/block/BucketSoundInteractionTranslator.java @@ -29,6 +29,7 @@ import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket; import org.geysermc.geyser.inventory.GeyserItemStack; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.sound.BlockSoundInteractionTranslator; import org.geysermc.geyser.translator.sound.SoundTranslator; @@ -37,7 +38,8 @@ import org.geysermc.geyser.translator.sound.SoundTranslator; public class BucketSoundInteractionTranslator implements BlockSoundInteractionTranslator { @Override - public void translate(GeyserSession session, Vector3f position, String identifier) { + public void translate(GeyserSession session, Vector3f position, BlockState state) { + String identifier = state.toString(); if (!session.isPlacedBucket()) { return; // No bucket was really interacted with } 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 e77539e6e..9d5d3cd59 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 @@ -28,6 +28,7 @@ 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.packet.LevelEventPacket; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.sound.BlockSoundInteractionTranslator; import org.geysermc.geyser.translator.sound.SoundTranslator; @@ -36,7 +37,8 @@ import org.geysermc.geyser.translator.sound.SoundTranslator; public class ComparatorSoundInteractionTranslator implements BlockSoundInteractionTranslator { @Override - public void translate(GeyserSession session, Vector3f position, String identifier) { + public void translate(GeyserSession session, Vector3f position, BlockState state) { + String identifier = state.toString(); boolean powered = identifier.contains("mode=compare"); LevelEventPacket levelEventPacket = new LevelEventPacket(); levelEventPacket.setPosition(position); diff --git a/core/src/main/java/org/geysermc/geyser/translator/sound/block/FlintAndSteelInteractionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/sound/block/FlintAndSteelInteractionTranslator.java index a822f3520..e8225a336 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/sound/block/FlintAndSteelInteractionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/sound/block/FlintAndSteelInteractionTranslator.java @@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.sound.block; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.sound.BlockSoundInteractionTranslator; import org.geysermc.geyser.translator.sound.SoundTranslator; @@ -36,7 +37,7 @@ import org.geysermc.geyser.translator.sound.SoundTranslator; public class FlintAndSteelInteractionTranslator implements BlockSoundInteractionTranslator { @Override - public void translate(GeyserSession session, Vector3f position, String identifier) { + public void translate(GeyserSession session, Vector3f position, BlockState state) { LevelSoundEventPacket levelSoundEventPacket = new LevelSoundEventPacket(); levelSoundEventPacket.setPosition(position); levelSoundEventPacket.setBabySound(false); diff --git a/core/src/main/java/org/geysermc/geyser/translator/sound/block/GrassPathInteractionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/sound/block/GrassPathInteractionTranslator.java index 0a91f8896..a25beaa50 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/sound/block/GrassPathInteractionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/sound/block/GrassPathInteractionTranslator.java @@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.sound.block; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.sound.BlockSoundInteractionTranslator; @@ -37,7 +38,8 @@ import org.geysermc.geyser.translator.sound.SoundTranslator; public class GrassPathInteractionTranslator implements BlockSoundInteractionTranslator { @Override - public void translate(GeyserSession session, Vector3f position, String identifier) { + public void translate(GeyserSession session, Vector3f position, BlockState state) { + String identifier = state.toString(); LevelSoundEventPacket levelSoundEventPacket = new LevelSoundEventPacket(); levelSoundEventPacket.setPosition(position); levelSoundEventPacket.setBabySound(false); diff --git a/core/src/main/java/org/geysermc/geyser/translator/sound/block/HoeInteractionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/sound/block/HoeInteractionTranslator.java index 410422b4a..1a583ab8a 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/sound/block/HoeInteractionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/sound/block/HoeInteractionTranslator.java @@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.sound.block; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.sound.BlockSoundInteractionTranslator; @@ -37,7 +38,8 @@ import org.geysermc.geyser.translator.sound.SoundTranslator; public class HoeInteractionTranslator implements BlockSoundInteractionTranslator { @Override - public void translate(GeyserSession session, Vector3f position, String identifier) { + public void translate(GeyserSession session, Vector3f position, BlockState state) { + String identifier = state.toString(); LevelSoundEventPacket levelSoundEventPacket = new LevelSoundEventPacket(); levelSoundEventPacket.setPosition(position); levelSoundEventPacket.setBabySound(false); 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 17b8768bc..fd045739c 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 @@ -28,6 +28,7 @@ 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.packet.LevelEventPacket; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.sound.BlockSoundInteractionTranslator; import org.geysermc.geyser.translator.sound.SoundTranslator; @@ -36,7 +37,8 @@ import org.geysermc.geyser.translator.sound.SoundTranslator; public class LeverSoundInteractionTranslator implements BlockSoundInteractionTranslator { @Override - public void translate(GeyserSession session, Vector3f position, String identifier) { + public void translate(GeyserSession session, Vector3f position, BlockState state) { + String identifier = state.toString(); boolean powered = identifier.contains("powered=true"); LevelEventPacket levelEventPacket = new LevelEventPacket(); levelEventPacket.setPosition(position); 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/OpenableSoundInteractionTranslator.java similarity index 55% rename from core/src/main/java/org/geysermc/geyser/translator/sound/block/DoorSoundInteractionTranslator.java rename to core/src/main/java/org/geysermc/geyser/translator/sound/block/OpenableSoundInteractionTranslator.java index 8f8ab8bf6..93d55ca33 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/OpenableSoundInteractionTranslator.java @@ -27,21 +27,42 @@ 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.SoundEvent; import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; +import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket; +import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.sound.BlockSoundInteractionTranslator; import org.geysermc.geyser.translator.sound.SoundTranslator; @SoundTranslator(blocks = {"door", "fence_gate"}) -public class DoorSoundInteractionTranslator implements BlockSoundInteractionTranslator { +public class OpenableSoundInteractionTranslator implements BlockSoundInteractionTranslator { @Override - public void translate(GeyserSession session, Vector3f position, String identifier) { + public void translate(GeyserSession session, Vector3f position, BlockState state) { + String identifier = state.toString(); if (identifier.contains("iron")) return; - LevelEventPacket levelEventPacket = new LevelEventPacket(); - levelEventPacket.setType(LevelEvent.SOUND_DOOR_OPEN); - levelEventPacket.setPosition(position); - levelEventPacket.setData(0); - session.sendUpstreamPacket(levelEventPacket); + SoundEvent event = getSound(identifier.contains("open=true"), identifier); + LevelSoundEventPacket levelSoundEventPacket = new LevelSoundEventPacket(); + levelSoundEventPacket.setPosition(position.add(0.5, 0.5, 0.5)); + levelSoundEventPacket.setBabySound(false); + levelSoundEventPacket.setRelativeVolumeDisabled(false); + levelSoundEventPacket.setIdentifier(":"); + levelSoundEventPacket.setSound(event); + levelSoundEventPacket.setExtraData(session.getBlockMappings().getBedrockBlock(state).getRuntimeId()); + session.sendUpstreamPacket(levelSoundEventPacket); + } + + private SoundEvent getSound(boolean open, String identifier) { + if (identifier.contains("_door")) { + return open ? SoundEvent.DOOR_OPEN : SoundEvent.DOOR_CLOSE; + } + + if (identifier.contains("_trapdoor")) { + return open ? SoundEvent.TRAPDOOR_OPEN : SoundEvent.TRAPDOOR_CLOSE; + } + + // Fence Gate + return open ? SoundEvent.FENCE_GATE_OPEN : SoundEvent.FENCE_GATE_CLOSE; } } 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 524d241db..693ce136a 100644 --- a/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java @@ -133,7 +133,7 @@ public final class SoundUtils { } if (sound == null) { 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."); + + "' was not a playable level sound, or has yet to be mapped to an enum in SoundEvent."); return; } @@ -144,7 +144,7 @@ public final class SoundUtils { // Minecraft Wiki: 2^(x/12) = Java pitch where x is -12 to 12 // Java sends the note value as above starting with -12 and ending at 12 // Bedrock has a number for each type of note, then proceeds up the scale by adding to that number - soundPacket.setExtraData(soundMapping.getExtraData() + (int)(Math.round((Math.log10(pitch) / Math.log10(2)) * 12)) + 12); + soundPacket.setExtraData(soundMapping.getExtraData() + (int) (Math.round((Math.log10(pitch) / Math.log10(2)) * 12)) + 12); } else if (sound == SoundEvent.PLACE && soundMapping.getExtraData() == -1) { if (!soundMapping.getIdentifier().equals(":")) { int javaId = BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getOrDefault(soundMapping.getIdentifier(), Block.JAVA_AIR_ID); From 74cabed67444e1a6b79ba6966df08b7c1e2bf6ca Mon Sep 17 00:00:00 2001 From: chris Date: Sat, 6 Jul 2024 20:47:49 +0200 Subject: [PATCH 142/233] Update to loom 1.7-SNAPSHOT, update gradle wrapper (#4820) --- gradle/libs.versions.toml | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 43462 -> 43453 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 78601024f..49c02d190 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -39,7 +39,7 @@ minecraft = "1.21" indra = "3.1.3" shadow = "8.1.1" architectury-plugin = "3.4-SNAPSHOT" -architectury-loom = "1.6-SNAPSHOT" +architectury-loom = "1.7-SNAPSHOT" minotaur = "2.8.7" lombok = "8.4" blossom = "2.1.0" diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index d64cd4917707c1f8861d8cb53dd15194d4248596..e6441136f3d4ba8a0da8d277868979cfbc8ad796 100644 GIT binary patch delta 34118 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 delta 34176 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 SGW6ptSs!X7{rG*o_g?|vpSEZK diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b82aa23a4..a4413138c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From cbd59de37b3026e21fd01f71b70df00503ed0d8a Mon Sep 17 00:00:00 2001 From: chris Date: Sat, 6 Jul 2024 23:14:15 +0200 Subject: [PATCH 143/233] Only apply door fix when we can actually access the old blockstate (#4827) --- .../java/org/geysermc/geyser/level/block/type/DoorBlock.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/DoorBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/DoorBlock.java index 2efbdb523..956d4b771 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/DoorBlock.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/DoorBlock.java @@ -40,7 +40,7 @@ public class DoorBlock extends Block { // Needed to check whether we must force the client to update the door state. String doubleBlockHalf = state.getValue(Properties.DOUBLE_BLOCK_HALF); - if (doubleBlockHalf.equals("lower")) { + if (!session.getGeyser().getWorldManager().hasOwnChunkCache() && doubleBlockHalf.equals("lower")) { BlockState oldBlockState = session.getGeyser().getWorldManager().blockAt(session, position); // If these are the same, it means that we already updated the lower door block (manually in the workaround below), // and we do not need to update the block in the cache/on the client side using the super.updateBlock() method again. From a807fa6bb5c19f12894d82361372393b4d13c97c Mon Sep 17 00:00:00 2001 From: LetsGoAway <68365423+letsgoawaydev@users.noreply.github.com> Date: Sun, 7 Jul 2024 17:27:49 +0800 Subject: [PATCH 144/233] Fix typo in version command (#4830) --- .../src/main/java/org/geysermc/geyser/network/GameProtocol.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 de995301a..1e9e76205 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -67,7 +67,7 @@ public final class GameProtocol { .minecraftVersion("1.20.80/1.20.81") .build())); SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(DEFAULT_BEDROCK_CODEC.toBuilder() - .minecraftVersion("1.21.0/1.20.1") + .minecraftVersion("1.21.0/1.21.1") .build())); } From e0af0a54b78ada10d14c94469c75739ba06b6295 Mon Sep 17 00:00:00 2001 From: strom <167184523+stromsoftware@users.noreply.github.com> Date: Sun, 7 Jul 2024 16:59:18 +0200 Subject: [PATCH 145/233] Fix: Text display passenger offsets (#4676) --- .../geyser/entity/EntityDefinitions.java | 4 +- .../geyser/entity/type/DisplayBaseEntity.java | 77 +++++++++++++++++++ .../geyser/entity/type/TextDisplayEntity.java | 18 +---- .../org/geysermc/geyser/util/EntityUtils.java | 24 ++++-- 4 files changed, 97 insertions(+), 26 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/entity/type/DisplayBaseEntity.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 1496f8a82..11b4a32d1 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -307,11 +307,11 @@ public final class EntityDefinitions { .addTranslator(MetadataType.INT, TNTEntity::setFuseLength) .build(); - EntityDefinition displayBase = EntityDefinition.inherited(entityBase.factory(), entityBase) + EntityDefinition displayBase = EntityDefinition.inherited(DisplayBaseEntity::new, entityBase) .addTranslator(null) // Interpolation delay .addTranslator(null) // Transformation interpolation duration .addTranslator(null) // Position/Rotation interpolation duration - .addTranslator(null) // Translation + .addTranslator(MetadataType.VECTOR3, DisplayBaseEntity::setTranslation) // Translation .addTranslator(null) // Scale .addTranslator(null) // Left rotation .addTranslator(null) // Right rotation diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/DisplayBaseEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/DisplayBaseEntity.java new file mode 100644 index 000000000..16587d125 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/entity/type/DisplayBaseEntity.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 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; + +import net.kyori.adventure.text.Component; +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.util.EntityUtils; +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; + +public class DisplayBaseEntity extends Entity { + + private @Nullable Vector3f baseTranslation; + + public DisplayBaseEntity(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 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. + } + + @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 setTranslation(EntityMetadata translationMeta){ + this.baseTranslation = translationMeta.getValue(); + if (this.baseTranslation == null) { + return; + } + if (this.vehicle == null) { + this.setRiderSeatPosition(this.baseTranslation); + this.moveRelative(this.baseTranslation.getX(), this.baseTranslation.getY(), this.baseTranslation.getZ(), yaw, pitch, headYaw, false); + } else { + EntityUtils.updateMountOffset(this, this.vehicle, true, true, false); + this.updateBedrockMetadata(); + } + } + + public Vector3f getTranslation() { + return baseTranslation; + } +} 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 28f38f919..ff5604c19 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2023 GeyserMC. http://geysermc.org + * Copyright (c) 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 @@ -32,13 +32,11 @@ 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; // Note: 1.19.4 requires that the billboard is set to something in order to show, on Java Edition -public class TextDisplayEntity extends Entity { +public class TextDisplayEntity extends DisplayBaseEntity { public TextDisplayEntity(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); } @@ -51,18 +49,6 @@ 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. - } - - @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())); } 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 bfb70a4ed..53aefde1e 100644 --- a/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/EntityUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * Copyright (c) 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 @@ -32,6 +32,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.type.BoatEntity; import org.geysermc.geyser.entity.type.Entity; +import org.geysermc.geyser.entity.type.TextDisplayEntity; import org.geysermc.geyser.entity.type.living.ArmorStandEntity; import org.geysermc.geyser.entity.type.living.animal.AnimalEntity; import org.geysermc.geyser.entity.type.living.animal.horse.CamelEntity; @@ -172,11 +173,7 @@ public final class EntityUtils { case BOAT -> { // Without the X offset, more than one entity on a boat is stacked on top of each other if (moreThanOneEntity) { - if (rider) { - xOffset = 0.2f; - } else { - xOffset = -0.6f; - } + xOffset = rider ? 0.2f : -0.6f; if (passenger instanceof AnimalEntity) { xOffset += 0.2f; } @@ -203,6 +200,18 @@ public final class EntityUtils { case CHEST_BOAT -> xOffset = 0.15F; case CHICKEN -> zOffset = -0.1f; case TRADER_LLAMA, LLAMA -> zOffset = -0.3f; + case TEXT_DISPLAY -> { + if (passenger instanceof TextDisplayEntity textDisplay) { + Vector3f displayTranslation = textDisplay.getTranslation(); + if (displayTranslation == null) { + return; + } + + xOffset = displayTranslation.getX(); + yOffset = displayTranslation.getY() + 0.2f; + zOffset = displayTranslation.getZ(); + } + } } /* * Bedrock Differences @@ -228,8 +237,7 @@ public final class EntityUtils { if (mount instanceof ArmorStandEntity armorStand) { yOffset -= armorStand.getYOffset(); } - Vector3f offset = Vector3f.from(xOffset, yOffset, zOffset); - passenger.setRiderSeatPosition(offset); + passenger.setRiderSeatPosition(Vector3f.from(xOffset, yOffset, zOffset)); } } From 0a928c41b01de14ef428b348f91d0226f2236968 Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 8 Jul 2024 00:41:00 +0200 Subject: [PATCH 146/233] Show potions & custom items in the shulker box tooltip (#4822) * Fix: Potions/Custom items showing up improperly in shulker box previews * oops --- .../geyser/item/type/ShulkerBoxItem.java | 31 +++++++++++++++++-- .../translator/item/BedrockItemBuilder.java | 9 +++++- 2 files changed, 37 insertions(+), 3 deletions(-) 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 a539fa739..c3b739adc 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 @@ -29,15 +29,19 @@ 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.definitions.ItemDefinition; +import org.geysermc.geyser.inventory.item.Potion; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.level.block.type.Block; 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.CustomItemTranslator; 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 org.geysermc.mcprotocollib.protocol.data.game.item.component.PotionContents; import java.util.ArrayList; import java.util.List; @@ -64,12 +68,35 @@ public class ShulkerBoxItem extends BlockItem { } ItemMapping boxMapping = session.getItemMappings().getMapping(item.getId()); - NbtMapBuilder boxItemNbt = BedrockItemBuilder.createItemNbt(boxMapping, item.getAmount(), boxMapping.getBedrockData()); // Final item tag to add to the list + int bedrockData = boxMapping.getBedrockData(); + String bedrockIdentifier = boxMapping.getBedrockIdentifier(); + DataComponents boxComponents = item.getDataComponents(); + + if (boxComponents != null) { + // Check for custom items + ItemDefinition customItemDefinition = CustomItemTranslator.getCustomItem(boxComponents, boxMapping); + if (customItemDefinition != null) { + bedrockIdentifier = customItemDefinition.getIdentifier(); + bedrockData = 0; + } else { + // Manual checks for potions/tipped arrows + if (boxMapping.getJavaItem() instanceof PotionItem || boxMapping.getJavaItem() instanceof ArrowItem) { + PotionContents potionContents = boxComponents.get(DataComponentType.POTION_CONTENTS); + if (potionContents != null) { + Potion potion = Potion.getByJavaId(potionContents.getPotionId()); + if (potion != null) { + bedrockData = potion.getBedrockId(); + } + } + } + } + } + + NbtMapBuilder boxItemNbt = BedrockItemBuilder.createItemNbt(bedrockIdentifier, item.getAmount(), bedrockData); // 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) { String customName = ItemTranslator.getCustomName(session, boxComponents, boxMapping, '7'); if (customName != null) { 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 52d5b7e31..e989288c2 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 @@ -145,8 +145,15 @@ public final class BedrockItemBuilder { * Creates item NBT to nest within NBT with name, count, and damage set. */ public static NbtMapBuilder createItemNbt(ItemMapping mapping, int count, int damage) { + return createItemNbt(mapping.getBedrockIdentifier(), count, damage); + } + + /** + * Creates item NBT to nest within NBT with name, count, and damage set. + */ + public static NbtMapBuilder createItemNbt(String bedrockIdentifier, int count, int damage) { NbtMapBuilder builder = NbtMap.builder(); - builder.putString("Name", mapping.getBedrockIdentifier()); + builder.putString("Name", bedrockIdentifier); builder.putByte("Count", (byte) count); builder.putShort("Damage", (short) damage); return builder; From f825007d9a5e5c3856aa09e05786f4dcb1f4102a Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 9 Jul 2024 12:39:43 -0400 Subject: [PATCH 147/233] Support Bedrock 1.21.2 --- .../org/geysermc/geyser/network/GameProtocol.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 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 1e9e76205..c79ef365d 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -43,13 +43,17 @@ import java.util.StringJoiner; */ public final class GameProtocol { + // Surprise protocol bump WOW + private static final BedrockCodec BEDROCK_V686 = Bedrock_v685.CODEC.toBuilder() + .protocolVersion(686) + .minecraftVersion("1.21.2") + .build(); + /** * 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_v685.CODEC.toBuilder() - .minecraftVersion("1.21.1") - .build()); + public static final BedrockCodec DEFAULT_BEDROCK_CODEC = CodecProcessor.processCodec(BEDROCK_V686); /** * A list of all supported Bedrock versions that can join Geyser @@ -66,9 +70,10 @@ public final class GameProtocol { SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v671.CODEC.toBuilder() .minecraftVersion("1.20.80/1.20.81") .build())); - SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(DEFAULT_BEDROCK_CODEC.toBuilder() + SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v685.CODEC.toBuilder() .minecraftVersion("1.21.0/1.21.1") .build())); + SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC); } /** From a3b1f203ec7d607644195d1630b0077a5fe211b5 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 9 Jul 2024 12:59:48 -0400 Subject: [PATCH 148/233] Bump Bedrock version in README --- README.md | 2 +- core/src/main/resources/mappings | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e3b5a496a..14bdb17a9 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.80 - 1.21.1 and Minecraft Java 1.21 +### Currently supporting Minecraft Bedrock 1.20.80 - 1.21.2 and Minecraft Java 1.21 ## Setting Up Take a look [here](https://wiki.geysermc.org/geyser/setup/) for how to set up Geyser. diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings index aaf53d695..23cb22f9c 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit aaf53d6953c927e5ac1b87fd6627ffbfd4aa7cf5 +Subproject commit 23cb22f9ceeb7f24b896a69a711944d7f3e756ed From 7fdb410d26f8759c906d6673eacce9f60d00ff4b Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 9 Jul 2024 13:00:27 -0400 Subject: [PATCH 149/233] Fix 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 23cb22f9c..aaf53d695 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 23cb22f9ceeb7f24b896a69a711944d7f3e756ed +Subproject commit aaf53d6953c927e5ac1b87fd6627ffbfd4aa7cf5 From 2a6025f3fc841f471c92b23fd2ed982eca36ae4f Mon Sep 17 00:00:00 2001 From: Eclipse Date: Wed, 10 Jul 2024 10:02:32 +0000 Subject: [PATCH 150/233] Fix reading enchantments from server (#4836) --- .../geyser/inventory/recipe/TrimRecipe.java | 21 ++++--- .../updater/AnvilInventoryUpdater.java | 27 +++++---- .../geyser/item/enchantment/Enchantment.java | 59 ++++++++++++++----- .../geysermc/geyser/level/JavaDimension.java | 6 +- .../geysermc/geyser/level/JukeboxSong.java | 8 +-- .../geyser/session/cache/RegistryCache.java | 38 ++++++++---- .../geyser/session/cache/TagCache.java | 8 ++- .../cache/registry/RegistryEntryContext.java | 56 ++++++++++++++++++ .../geysermc/geyser/text/TextDecoration.java | 6 +- 9 files changed, 166 insertions(+), 63 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/session/cache/registry/RegistryEntryContext.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 8289813a4..b5e76a296 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 @@ -32,9 +32,8 @@ 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 org.geysermc.geyser.registry.type.ItemMapping; -import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.registry.RegistryEntryContext; 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. @@ -46,18 +45,18 @@ public final class TrimRecipe { public static final ItemDescriptorWithCount ADDITION = tagDescriptor("minecraft:trim_materials"); public static final ItemDescriptorWithCount TEMPLATE = tagDescriptor("minecraft:trim_templates"); - public static TrimMaterial readTrimMaterial(GeyserSession session, RegistryEntry entry) { - String key = entry.getId().asMinimalString(); + public static TrimMaterial readTrimMaterial(RegistryEntryContext context) { + String key = context.id().asMinimalString(); // 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!!!!! - String colorTag = entry.getData().getCompound("description").getString("color"); + String colorTag = context.data().getCompound("description").getString("color"); TextColor color = TextColor.fromHexString(colorTag); String legacy = MessageTranslator.convertMessage(Component.space().color(color)); - String itemIdentifier = entry.getData().getString("ingredient"); - ItemMapping itemMapping = session.getItemMappings().getMapping(itemIdentifier); + String itemIdentifier = context.data().getString("ingredient"); + ItemMapping itemMapping = context.session().getItemMappings().getMapping(itemIdentifier); if (itemMapping == null) { // This should never happen so not sure what to do here. itemMapping = ItemMapping.AIR; @@ -66,11 +65,11 @@ public final class TrimRecipe { return new TrimMaterial(key, legacy.substring(2).trim(), itemMapping.getBedrockIdentifier()); } - public static TrimPattern readTrimPattern(GeyserSession session, RegistryEntry entry) { - String key = entry.getId().asMinimalString(); + public static TrimPattern readTrimPattern(RegistryEntryContext context) { + String key = context.id().asMinimalString(); - String itemIdentifier = entry.getData().getString("template_item"); - ItemMapping itemMapping = session.getItemMappings().getMapping(itemIdentifier); + String itemIdentifier = context.data().getString("template_item"); + ItemMapping itemMapping = context.session().getItemMappings().getMapping(itemIdentifier); if (itemMapping == null) { // This should never happen so not sure what to do here. itemMapping = ItemMapping.AIR; 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 c3ac73372..7afd31cc9 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 @@ -27,6 +27,7 @@ package org.geysermc.geyser.inventory.updater; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import java.util.stream.IntStream; import net.kyori.adventure.text.Component; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; @@ -41,11 +42,14 @@ import org.geysermc.geyser.inventory.item.BedrockEnchantment; import org.geysermc.geyser.item.enchantment.Enchantment; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.tags.EnchantmentTag; +import org.geysermc.geyser.session.cache.tags.ItemTag; 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.HolderSet; import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemEnchantments; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket; @@ -310,17 +314,18 @@ public class AnvilInventoryUpdater extends InventoryUpdater { for (Object2IntMap.Entry entry : getEnchantments(session, material).object2IntEntrySet()) { Enchantment enchantment = entry.getKey(); - boolean canApply = isEnchantedBook(input) || session.getTagCache().is(enchantment.supportedItems(), input); - var exclusiveSet = enchantment.exclusiveSet(); - if (exclusiveSet != null) { - int[] incompatibleEnchantments = session.getTagCache().get(exclusiveSet); - for (int i : incompatibleEnchantments) { - Enchantment incompatible = session.getRegistryCache().enchantments().byId(i); - if (combinedEnchantments.containsKey(incompatible)) { - canApply = false; - if (!bedrock) { - cost++; - } + HolderSet supportedItems = enchantment.supportedItems(); + int[] supportedItemIds = supportedItems.resolve(tagId -> session.getTagCache().get(ItemTag.ALL_ITEM_TAGS.get(tagId))); + boolean canApply = isEnchantedBook(input) || IntStream.of(supportedItemIds).anyMatch(id -> id == input.getJavaId()); + + HolderSet exclusiveSet = enchantment.exclusiveSet(); + int[] incompatibleEnchantments = exclusiveSet.resolve(tagId -> session.getTagCache().get(EnchantmentTag.ALL_ENCHANTMENT_TAGS.get(tagId))); + for (int i : incompatibleEnchantments) { + Enchantment incompatible = session.getRegistryCache().enchantments().byId(i); + if (combinedEnchantments.containsKey(incompatible)) { + canApply = false; + if (!bedrock) { + cost++; } } } diff --git a/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java b/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java index c5c0d2611..3c0caa60c 100644 --- a/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java +++ b/core/src/main/java/org/geysermc/geyser/item/enchantment/Enchantment.java @@ -25,18 +25,21 @@ package org.geysermc.geyser.item.enchantment; +import java.util.List; +import java.util.function.Function; +import net.kyori.adventure.key.Key; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtMap; import org.geysermc.geyser.inventory.item.BedrockEnchantment; -import org.geysermc.geyser.session.cache.tags.EnchantmentTag; -import org.geysermc.geyser.session.cache.tags.ItemTag; +import org.geysermc.geyser.item.Items; +import org.geysermc.geyser.registry.Registries; +import org.geysermc.geyser.session.cache.registry.RegistryEntryContext; import org.geysermc.geyser.translator.text.MessageTranslator; -import org.geysermc.geyser.util.MinecraftKey; -import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; import java.util.HashSet; import java.util.Map; import java.util.Set; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.HolderSet; /** * @param description only populated if {@link #bedrockEnchantment()} is not null. @@ -44,28 +47,32 @@ import java.util.Set; */ public record Enchantment(String identifier, Set effects, - ItemTag supportedItems, + HolderSet supportedItems, int maxLevel, String description, int anvilCost, - @Nullable EnchantmentTag exclusiveSet, + HolderSet exclusiveSet, @Nullable BedrockEnchantment bedrockEnchantment) { - // Implementation note: I have a feeling the tags can be a list of items, because in vanilla they're HolderSet classes. - // I'm not sure how that's wired over the network, so we'll put it off. - public static Enchantment read(RegistryEntry entry) { - NbtMap data = entry.getData(); + public static Enchantment read(RegistryEntryContext context) { + NbtMap data = context.data(); Set effects = readEnchantmentComponents(data.getCompound("effects")); - String supportedItems = data.getString("supported_items").substring(1); // Remove '#' at beginning that indicates tag + + HolderSet supportedItems = readHolderSet(data.get("supported_items"), itemId -> Registries.JAVA_ITEM_IDENTIFIERS.getOrDefault(itemId.asString(), Items.AIR).javaId()); + int maxLevel = data.getInt("max_level"); int anvilCost = data.getInt("anvil_cost"); - String exclusiveSet = data.getString("exclusive_set", null); - EnchantmentTag exclusiveSetTag = exclusiveSet == null ? null : EnchantmentTag.ALL_ENCHANTMENT_TAGS.get(MinecraftKey.key(exclusiveSet.substring(1))); - BedrockEnchantment bedrockEnchantment = BedrockEnchantment.getByJavaIdentifier(entry.getId().asString()); + + HolderSet exclusiveSet = readHolderSet(data.getOrDefault("exclusive_set", null), context::getNetworkId); + + BedrockEnchantment bedrockEnchantment = BedrockEnchantment.getByJavaIdentifier(context.id().asString()); + + // TODO - description is a component. So if a hardcoded literal string is given, this will display normally on Java, + // but Geyser will attempt to lookup the literal string as translation - and will fail, displaying an empty string as enchantment name. String description = bedrockEnchantment == null ? MessageTranslator.deserializeDescription(data) : null; - return new Enchantment(entry.getId().asString(), effects, ItemTag.ALL_ITEM_TAGS.get(MinecraftKey.key(supportedItems)), maxLevel, - description, anvilCost, exclusiveSetTag, bedrockEnchantment); + return new Enchantment(context.id().asString(), effects, supportedItems, maxLevel, + description, anvilCost, exclusiveSet, bedrockEnchantment); } private static Set readEnchantmentComponents(NbtMap effects) { @@ -77,4 +84,24 @@ public record Enchantment(String identifier, } return Set.copyOf(components); // Also ensures any empty sets are consolidated } + + // TODO holder set util? + private static HolderSet readHolderSet(@Nullable Object holderSet, Function keyIdMapping) { + if (holderSet == null) { + return new HolderSet(new int[]{}); + } + + if (holderSet instanceof String stringTag) { + // Tag + if (stringTag.startsWith("#")) { + return new HolderSet(Key.key(stringTag.substring(1))); // Remove '#' at beginning that indicates tag + } else { + return new HolderSet(new int[]{keyIdMapping.apply(Key.key(stringTag))}); + } + } else if (holderSet instanceof List list) { + // Assume the list is a list of strings + return new HolderSet(list.stream().map(o -> (String) o).map(Key::key).map(keyIdMapping).mapToInt(Integer::intValue).toArray()); + } + throw new IllegalArgumentException("Holder set must either be a tag, a string ID or a list of string IDs"); + } } 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 6112dc6cf..dd0f4215e 100644 --- a/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java +++ b/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java @@ -26,7 +26,7 @@ package org.geysermc.geyser.level; import org.cloudburstmc.nbt.NbtMap; -import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; +import org.geysermc.geyser.session.cache.registry.RegistryEntryContext; /** * Represents the information we store from the current Java dimension @@ -35,8 +35,8 @@ import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; */ public record JavaDimension(int minY, int maxY, boolean piglinSafe, double worldCoordinateScale) { - public static JavaDimension read(RegistryEntry entry) { - NbtMap dimension = entry.getData(); + public static JavaDimension read(RegistryEntryContext entry) { + NbtMap dimension = entry.data(); 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. diff --git a/core/src/main/java/org/geysermc/geyser/level/JukeboxSong.java b/core/src/main/java/org/geysermc/geyser/level/JukeboxSong.java index 156a62cd1..b00dc9f98 100644 --- a/core/src/main/java/org/geysermc/geyser/level/JukeboxSong.java +++ b/core/src/main/java/org/geysermc/geyser/level/JukeboxSong.java @@ -27,13 +27,13 @@ package org.geysermc.geyser.level; import org.cloudburstmc.nbt.NbtMap; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.session.cache.registry.RegistryEntryContext; import org.geysermc.geyser.translator.text.MessageTranslator; -import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; public record JukeboxSong(String soundEvent, String description) { - public static JukeboxSong read(RegistryEntry entry) { - NbtMap data = entry.getData(); + public static JukeboxSong read(RegistryEntryContext context) { + NbtMap data = context.data(); Object soundEventObject = data.get("sound_event"); String soundEvent; if (soundEventObject instanceof NbtMap map) { @@ -42,7 +42,7 @@ public record JukeboxSong(String soundEvent, String description) { soundEvent = string; } else { soundEvent = ""; - GeyserImpl.getInstance().getLogger().debug("Sound event for " + entry.getId() + " was of an unexpected type! Expected string or NBT map, got " + soundEventObject); + GeyserImpl.getInstance().getLogger().debug("Sound event for " + context.id() + " was of an unexpected type! Expected string or NBT map, got " + soundEventObject); } String description = MessageTranslator.deserializeDescription(data); return new JukeboxSong(soundEvent, description); 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 3121af369..a393d461d 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,6 +27,8 @@ 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.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import lombok.AccessLevel; import lombok.Getter; import lombok.experimental.Accessors; @@ -45,6 +47,7 @@ import org.geysermc.geyser.level.JukeboxSong; import org.geysermc.geyser.level.PaintingType; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.registry.JavaRegistry; +import org.geysermc.geyser.session.cache.registry.RegistryEntryContext; import org.geysermc.geyser.session.cache.registry.SimpleJavaRegistry; import org.geysermc.geyser.text.TextDecoration; import org.geysermc.geyser.translator.level.BiomeTranslator; @@ -59,7 +62,6 @@ 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; @@ -76,16 +78,16 @@ 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("enchantment", cache -> cache.enchantments, ($, entry) -> Enchantment.read(entry)); - register("jukebox_song", cache -> cache.jukeboxSongs, ($, entry) -> JukeboxSong.read(entry)); - register("painting_variant", cache -> cache.paintings, ($, entry) -> PaintingType.getByName(entry.getId())); + register("chat_type", cache -> cache.chatTypes, TextDecoration::readChatType); + register("dimension_type", cache -> cache.dimensions, JavaDimension::read); + register("enchantment", cache -> cache.enchantments, Enchantment::read); + register("jukebox_song", cache -> cache.jukeboxSongs, JukeboxSong::read); + register("painting_variant", cache -> cache.paintings, context -> PaintingType.getByName(context.id())); 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())); - register("wolf_variant", cache -> cache.wolfVariants, ($, entry) -> WolfEntity.BuiltInWolfVariant.getByJavaIdentifier(entry.getId().asString())); + register("banner_pattern", cache -> cache.bannerPatterns, context -> BannerPattern.getByJavaIdentifier(context.id())); + register("wolf_variant", cache -> cache.wolfVariants, context -> WolfEntity.BuiltInWolfVariant.getByJavaIdentifier(context.id().asString())); // Load from MCProtocolLib's classloader NbtMap tag = MinecraftProtocol.loadNetworkCodec(); @@ -149,25 +151,35 @@ public final class RegistryCache { * @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) { - Key key = MinecraftKey.key(registry); - REGISTRIES.put(key, (registryCache, entries) -> { + private static void register(String registry, Function> localCacheFunction, Function reader) { + Key registryKey = MinecraftKey.key(registry); + REGISTRIES.put(registryKey, (registryCache, entries) -> { Map localRegistry = null; JavaRegistry localCache = localCacheFunction.apply(registryCache); // Clear each local cache every time a new registry entry is given to us // (e.g. proxy server switches) + + // Store each of the entries resource location IDs and their respective network ID, + // used for the key mapper that's currently only used by the Enchantment class + Object2IntMap entryIdMap = new Object2IntOpenHashMap<>(); + for (int i = 0; i < entries.size(); i++) { + entryIdMap.put(entries.get(i).getId(), i); + } + List builder = new ArrayList<>(entries.size()); for (int i = 0; i < entries.size(); i++) { RegistryEntry entry = entries.get(i); // If the data is null, that's the server telling us we need to use our default values. if (entry.getData() == null) { if (localRegistry == null) { // Lazy initialize - localRegistry = DEFAULTS.get(key); + localRegistry = DEFAULTS.get(registryKey); } entry = new RegistryEntry(entry.getId(), localRegistry.get(entry.getId())); } + + RegistryEntryContext context = new RegistryEntryContext(entry, entryIdMap, registryCache.session); // This is what Geyser wants to keep as a value for this registry. - T cacheEntry = reader.apply(registryCache.session, entry); + T cacheEntry = reader.apply(context); builder.add(i, cacheEntry); } localCache.reset(builder); 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 c8bfc7eed..f4d69dcdb 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 @@ -130,8 +130,12 @@ public final class TagCache { return contains(values, item.javaId()); } - public int[] get(EnchantmentTag tag) { - return this.enchantments[tag.ordinal()]; + public int[] get(ItemTag itemTag) { + return this.items[itemTag.ordinal()]; + } + + public int[] get(EnchantmentTag enchantmentTag) { + return this.enchantments[enchantmentTag.ordinal()]; } private static boolean contains(int[] array, int i) { diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/registry/RegistryEntryContext.java b/core/src/main/java/org/geysermc/geyser/session/cache/registry/RegistryEntryContext.java new file mode 100644 index 000000000..415890d95 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/session/cache/registry/RegistryEntryContext.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 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.Object2IntMap; +import java.util.Map; +import net.kyori.adventure.key.Key; +import org.cloudburstmc.nbt.NbtMap; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; + +/** + * Used to store context around a single registry entry when reading said entry's NBT. + * + * @param entry the registry entry being read. + * @param keyIdMap a map for each of the resource location's in the registry and their respective network IDs. + * @param session the Geyser session. + */ +public record RegistryEntryContext(RegistryEntry entry, Object2IntMap keyIdMap, GeyserSession session) { + + public int getNetworkId(Key registryKey) { + return keyIdMap.getOrDefault(registryKey, 0); + } + + public Key id() { + return entry.getId(); + } + + // Not annotated as nullable because data should never be null here + public NbtMap data() { + return entry.getData(); + } +} 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 ab9e2b5ed..94aec22ef 100644 --- a/core/src/main/java/org/geysermc/geyser/text/TextDecoration.java +++ b/core/src/main/java/org/geysermc/geyser/text/TextDecoration.java @@ -29,7 +29,7 @@ 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 org.geysermc.geyser.session.cache.registry.RegistryEntryContext; import org.geysermc.mcprotocollib.protocol.data.game.chat.ChatType; import org.geysermc.mcprotocollib.protocol.data.game.chat.ChatTypeDecoration; @@ -43,11 +43,11 @@ public record TextDecoration(String translationKey, List parameters, throw new UnsupportedOperationException(); } - public static ChatType readChatType(RegistryEntry entry) { + public static ChatType readChatType(RegistryEntryContext context) { // Note: The ID is NOT ALWAYS THE SAME! ViaVersion as of 1.19 adds two registry entries that do NOT match vanilla. // (This note has been passed around through several classes and iterations. It stays as a warning // to anyone that dares to try and hardcode registry IDs.) - NbtMap tag = entry.getData(); + NbtMap tag = context.data(); NbtMap chat = tag.getCompound("chat", null); if (chat != null) { String translationKey = chat.getString("translation_key"); From 93b0a612659d026a293a53f632f89d1c5775eacf Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 12 Jul 2024 20:55:40 +0200 Subject: [PATCH 151/233] Fix: hanging sign recipe not showing up in the recipe book (#4814) --- .../populator/CreativeItemRegistryPopulator.java | 12 +----------- .../registry/populator/ItemRegistryPopulator.java | 7 ++----- 2 files changed, 3 insertions(+), 16 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 c536d739c..2c033edc7 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 @@ -49,8 +49,6 @@ import java.util.function.Consumer; public class CreativeItemRegistryPopulator { private static final List> JAVA_ONLY_ITEM_FILTER = List.of( - // Just shows an empty texture; either way it doesn't exist in the creative menu on Java - (identifier, data) -> identifier.equals("minecraft:debug_stick"), // Bedrock-only as its own item (identifier, data) -> identifier.equals("minecraft:empty_map") && data == 2, // Bedrock-only banner patterns @@ -103,16 +101,8 @@ public class CreativeItemRegistryPopulator { } 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) { + if ((blockStateNode = itemNode.get("block_state_b64")) != null) { byte[] bytes = Base64.getDecoder().decode(blockStateNode.asText()); ByteArrayInputStream bais = new ByteArrayInputStream(bytes); try { 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 e19066462..85207ac3a 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 @@ -252,10 +252,7 @@ public class ItemRegistryPopulator { } else { // Try to get an example block runtime ID from the creative contents packet, for Bedrock identifier obtaining int aValidBedrockBlockId = blacklistedIdentifiers.getOrDefault(bedrockIdentifier, customBlockItemOverride != null ? customBlockItemOverride.getRuntimeId() : -1); - if (aValidBedrockBlockId == -1 && customBlockItemOverride == null) { - // Fallback - bedrockBlock = blockMappings.getBedrockBlock(firstBlockRuntimeId); - } else { + if (aValidBedrockBlockId != -1 || customBlockItemOverride != null) { // As of 1.16.220, every item requires a block runtime ID attached to it. // This is mostly for identifying different blocks with the same item ID - wool, slabs, some walls. // However, in order for some visuals and crafting to work, we need to send the first matching block state @@ -266,7 +263,7 @@ public class ItemRegistryPopulator { boolean firstPass = true; // Block states are all grouped together. In the mappings, we store the first block runtime ID in order, // 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(); + int lastBlockRuntimeId = entry.getValue().getLastBlockRuntimeId() == null ? firstBlockRuntimeId : entry.getValue().getLastBlockRuntimeId(); for (int i = firstBlockRuntimeId; i <= lastBlockRuntimeId; i++) { GeyserBedrockBlock bedrockBlockRuntimeId = blockMappings.getVanillaBedrockBlock(i); NbtMap blockTag = bedrockBlockRuntimeId.getState(); From b0c7ddb68dbf3141f9710ea970e5f06fd246c2a4 Mon Sep 17 00:00:00 2001 From: chris Date: Sat, 13 Jul 2024 18:53:13 +0200 Subject: [PATCH 152/233] Fix: Item color names/glint for rare items (#4763) * debug stick changes * yay light purple item name * Address review * Auto-generate rarity * Add glint generation * Translate all rare items properly * Use putIfAbsent instead of double checks --- .../java/org/geysermc/geyser/item/Items.java | 121 +++++++++--------- .../geyser/item/components/Rarity.java | 51 ++++++++ .../org/geysermc/geyser/item/type/Item.java | 25 ++++ .../populator/ItemRegistryPopulator.java | 4 +- .../translator/item/ItemTranslator.java | 34 +++-- 5 files changed, 163 insertions(+), 72 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/item/components/Rarity.java 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 1ddd14982..462e98d19 100644 --- a/core/src/main/java/org/geysermc/geyser/item/Items.java +++ b/core/src/main/java/org/geysermc/geyser/item/Items.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.item; +import org.geysermc.geyser.item.components.Rarity; import org.geysermc.geyser.item.components.ToolTier; import org.geysermc.geyser.item.type.*; import org.geysermc.geyser.level.block.Blocks; @@ -122,7 +123,7 @@ public final class Items { public static final Item RAW_IRON_BLOCK = register(new BlockItem(builder(), Blocks.RAW_IRON_BLOCK)); public static final Item RAW_COPPER_BLOCK = register(new BlockItem(builder(), Blocks.RAW_COPPER_BLOCK)); public static final Item RAW_GOLD_BLOCK = register(new BlockItem(builder(), Blocks.RAW_GOLD_BLOCK)); - public static final Item HEAVY_CORE = register(new BlockItem(builder(), Blocks.HEAVY_CORE)); + public static final Item HEAVY_CORE = register(new BlockItem(builder().rarity(Rarity.EPIC), Blocks.HEAVY_CORE)); public static final Item AMETHYST_BLOCK = register(new BlockItem(builder(), Blocks.AMETHYST_BLOCK)); public static final Item BUDDING_AMETHYST = register(new BlockItem(builder(), Blocks.BUDDING_AMETHYST)); public static final Item IRON_BLOCK = register(new BlockItem(builder(), Blocks.IRON_BLOCK)); @@ -416,7 +417,7 @@ public final class Items { public static final Item END_PORTAL_FRAME = register(new BlockItem(builder(), Blocks.END_PORTAL_FRAME)); public static final Item END_STONE = register(new BlockItem(builder(), Blocks.END_STONE)); public static final Item END_STONE_BRICKS = register(new BlockItem(builder(), Blocks.END_STONE_BRICKS)); - public static final Item DRAGON_EGG = register(new BlockItem(builder(), Blocks.DRAGON_EGG)); + public static final Item DRAGON_EGG = register(new BlockItem(builder().rarity(Rarity.EPIC), Blocks.DRAGON_EGG)); public static final Item SANDSTONE_STAIRS = register(new BlockItem(builder(), Blocks.SANDSTONE_STAIRS)); public static final Item ENDER_CHEST = register(new BlockItem(builder(), Blocks.ENDER_CHEST)); public static final Item EMERALD_BLOCK = register(new BlockItem(builder(), Blocks.EMERALD_BLOCK)); @@ -432,8 +433,8 @@ public final class Items { public static final Item BAMBOO_MOSAIC_STAIRS = register(new BlockItem(builder(), Blocks.BAMBOO_MOSAIC_STAIRS)); public static final Item CRIMSON_STAIRS = register(new BlockItem(builder(), Blocks.CRIMSON_STAIRS)); public static final Item WARPED_STAIRS = register(new BlockItem(builder(), Blocks.WARPED_STAIRS)); - public static final Item COMMAND_BLOCK = register(new BlockItem(builder(), Blocks.COMMAND_BLOCK)); - public static final Item BEACON = register(new BlockItem(builder(), Blocks.BEACON)); + public static final Item COMMAND_BLOCK = register(new BlockItem(builder().rarity(Rarity.EPIC), Blocks.COMMAND_BLOCK)); + public static final Item BEACON = register(new BlockItem(builder().rarity(Rarity.RARE), Blocks.BEACON)); public static final Item COBBLESTONE_WALL = register(new BlockItem(builder(), Blocks.COBBLESTONE_WALL)); public static final Item MOSSY_COBBLESTONE_WALL = register(new BlockItem(builder(), Blocks.MOSSY_COBBLESTONE_WALL)); public static final Item BRICK_WALL = register(new BlockItem(builder(), Blocks.BRICK_WALL)); @@ -480,8 +481,8 @@ public final class Items { public static final Item GREEN_TERRACOTTA = register(new BlockItem(builder(), Blocks.GREEN_TERRACOTTA)); public static final Item RED_TERRACOTTA = register(new BlockItem(builder(), Blocks.RED_TERRACOTTA)); public static final Item BLACK_TERRACOTTA = register(new BlockItem(builder(), Blocks.BLACK_TERRACOTTA)); - public static final Item BARRIER = register(new BlockItem(builder(), Blocks.BARRIER)); - public static final Item LIGHT = register(new BlockItem(builder(), Blocks.LIGHT)); + public static final Item BARRIER = register(new BlockItem(builder().rarity(Rarity.EPIC), Blocks.BARRIER)); + public static final Item LIGHT = register(new BlockItem(builder().rarity(Rarity.EPIC), Blocks.LIGHT)); public static final Item HAY_BLOCK = register(new BlockItem(builder(), Blocks.HAY_BLOCK)); public static final Item WHITE_CARPET = register(new BlockItem(builder(), Blocks.WHITE_CARPET)); public static final Item ORANGE_CARPET = register(new BlockItem(builder(), Blocks.ORANGE_CARPET)); @@ -551,14 +552,14 @@ public final class Items { public static final Item CHISELED_RED_SANDSTONE = register(new BlockItem(builder(), Blocks.CHISELED_RED_SANDSTONE)); public static final Item CUT_RED_SANDSTONE = register(new BlockItem(builder(), Blocks.CUT_RED_SANDSTONE)); public static final Item RED_SANDSTONE_STAIRS = register(new BlockItem(builder(), Blocks.RED_SANDSTONE_STAIRS)); - public static final Item REPEATING_COMMAND_BLOCK = register(new BlockItem(builder(), Blocks.REPEATING_COMMAND_BLOCK)); - public static final Item CHAIN_COMMAND_BLOCK = register(new BlockItem(builder(), Blocks.CHAIN_COMMAND_BLOCK)); + public static final Item REPEATING_COMMAND_BLOCK = register(new BlockItem(builder().rarity(Rarity.EPIC), Blocks.REPEATING_COMMAND_BLOCK)); + public static final Item CHAIN_COMMAND_BLOCK = register(new BlockItem(builder().rarity(Rarity.EPIC), Blocks.CHAIN_COMMAND_BLOCK)); public static final Item MAGMA_BLOCK = register(new BlockItem(builder(), Blocks.MAGMA_BLOCK)); public static final Item NETHER_WART_BLOCK = register(new BlockItem(builder(), Blocks.NETHER_WART_BLOCK)); public static final Item WARPED_WART_BLOCK = register(new BlockItem(builder(), Blocks.WARPED_WART_BLOCK)); public static final Item RED_NETHER_BRICKS = register(new BlockItem(builder(), Blocks.RED_NETHER_BRICKS)); public static final Item BONE_BLOCK = register(new BlockItem(builder(), Blocks.BONE_BLOCK)); - public static final Item STRUCTURE_VOID = register(new BlockItem(builder(), Blocks.STRUCTURE_VOID)); + public static final Item STRUCTURE_VOID = register(new BlockItem(builder().rarity(Rarity.EPIC), Blocks.STRUCTURE_VOID)); public static final Item SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.SHULKER_BOX)); public static final Item WHITE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.WHITE_SHULKER_BOX)); public static final Item ORANGE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.ORANGE_SHULKER_BOX)); @@ -657,7 +658,7 @@ public final class Items { public static final Item DEAD_FIRE_CORAL_FAN = register(new BlockItem(builder(), Blocks.DEAD_FIRE_CORAL_FAN, Blocks.DEAD_FIRE_CORAL_WALL_FAN)); public static final Item DEAD_HORN_CORAL_FAN = register(new BlockItem(builder(), Blocks.DEAD_HORN_CORAL_FAN, Blocks.DEAD_HORN_CORAL_WALL_FAN)); public static final Item BLUE_ICE = register(new BlockItem(builder(), Blocks.BLUE_ICE)); - public static final Item CONDUIT = register(new BlockItem(builder(), Blocks.CONDUIT)); + public static final Item CONDUIT = register(new BlockItem(builder().rarity(Rarity.RARE), Blocks.CONDUIT)); public static final Item POLISHED_GRANITE_STAIRS = register(new BlockItem(builder(), Blocks.POLISHED_GRANITE_STAIRS)); public static final Item SMOOTH_RED_SANDSTONE_STAIRS = register(new BlockItem(builder(), Blocks.SMOOTH_RED_SANDSTONE_STAIRS)); public static final Item MOSSY_STONE_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.MOSSY_STONE_BRICK_STAIRS)); @@ -810,7 +811,7 @@ public final class Items { public static final Item HOPPER_MINECART = register(new Item("hopper_minecart", builder().stackSize(1))); public static final Item CARROT_ON_A_STICK = register(new Item("carrot_on_a_stick", builder().stackSize(1).maxDamage(25))); public static final Item WARPED_FUNGUS_ON_A_STICK = register(new Item("warped_fungus_on_a_stick", builder().stackSize(1).maxDamage(100))); - public static final Item ELYTRA = register(new ElytraItem("elytra", builder().stackSize(1).maxDamage(432))); + public static final Item ELYTRA = register(new ElytraItem("elytra", builder().stackSize(1).maxDamage(432).rarity(Rarity.UNCOMMON))); public static final Item OAK_BOAT = register(new BoatItem("oak_boat", builder().stackSize(1))); public static final Item OAK_CHEST_BOAT = register(new BoatItem("oak_chest_boat", builder().stackSize(1))); public static final Item SPRUCE_BOAT = register(new BoatItem("spruce_boat", builder().stackSize(1))); @@ -829,8 +830,8 @@ public final class Items { public static final Item MANGROVE_CHEST_BOAT = register(new BoatItem("mangrove_chest_boat", builder().stackSize(1))); public static final Item BAMBOO_RAFT = register(new BoatItem("bamboo_raft", builder().stackSize(1))); public static final Item BAMBOO_CHEST_RAFT = register(new BoatItem("bamboo_chest_raft", builder().stackSize(1))); - public static final Item STRUCTURE_BLOCK = register(new BlockItem(builder(), Blocks.STRUCTURE_BLOCK)); - public static final Item JIGSAW = register(new BlockItem(builder(), Blocks.JIGSAW)); + public static final Item STRUCTURE_BLOCK = register(new BlockItem(builder().rarity(Rarity.EPIC), Blocks.STRUCTURE_BLOCK)); + public static final Item JIGSAW = register(new BlockItem(builder().rarity(Rarity.EPIC), Blocks.JIGSAW)); public static final Item TURTLE_HELMET = register(new ArmorItem("turtle_helmet", ArmorMaterial.TURTLE, builder().stackSize(1).maxDamage(275))); public static final Item TURTLE_SCUTE = register(new Item("turtle_scute", builder())); public static final Item ARMADILLO_SCUTE = register(new Item("armadillo_scute", builder())); @@ -921,8 +922,8 @@ public final class Items { public static final Item PORKCHOP = register(new Item("porkchop", builder())); public static final Item COOKED_PORKCHOP = register(new Item("cooked_porkchop", builder())); public static final Item PAINTING = register(new Item("painting", builder())); - public static final Item GOLDEN_APPLE = register(new Item("golden_apple", builder())); - public static final Item ENCHANTED_GOLDEN_APPLE = register(new Item("enchanted_golden_apple", builder())); + public static final Item GOLDEN_APPLE = register(new Item("golden_apple", builder().rarity(Rarity.RARE))); + public static final Item ENCHANTED_GOLDEN_APPLE = register(new Item("enchanted_golden_apple", builder().rarity(Rarity.EPIC))); public static final Item OAK_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.OAK_SIGN, Blocks.OAK_WALL_SIGN)); public static final Item SPRUCE_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.SPRUCE_SIGN, Blocks.SPRUCE_WALL_SIGN)); public static final Item BIRCH_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.BIRCH_SIGN, Blocks.BIRCH_WALL_SIGN)); @@ -1042,7 +1043,7 @@ public final class Items { public static final Item BLAZE_POWDER = register(new Item("blaze_powder", builder())); public static final Item MAGMA_CREAM = register(new Item("magma_cream", builder())); public static final Item BREWING_STAND = register(new BlockItem(builder(), Blocks.BREWING_STAND)); - public static final Item CAULDRON = register(new BlockItem(builder(), Blocks.CAULDRON, Blocks.WATER_CAULDRON, Blocks.LAVA_CAULDRON, Blocks.POWDER_SNOW_CAULDRON)); + public static final Item CAULDRON = register(new BlockItem(builder(), Blocks.CAULDRON, Blocks.WATER_CAULDRON, Blocks.POWDER_SNOW_CAULDRON, Blocks.LAVA_CAULDRON)); 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())); @@ -1125,12 +1126,12 @@ public final class Items { public static final Item ZOMBIE_HORSE_SPAWN_EGG = register(new SpawnEggItem("zombie_horse_spawn_egg", builder())); public static final Item ZOMBIE_VILLAGER_SPAWN_EGG = register(new SpawnEggItem("zombie_villager_spawn_egg", builder())); 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 EXPERIENCE_BOTTLE = register(new Item("experience_bottle", builder().rarity(Rarity.UNCOMMON))); 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(500))); + public static final Item MACE = register(new MaceItem("mace", builder().stackSize(1).maxDamage(500).rarity(Rarity.EPIC))); 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(builder(), Blocks.FLOWER_POT)); @@ -1140,18 +1141,18 @@ public final class Items { public static final Item POISONOUS_POTATO = register(new Item("poisonous_potato", builder())); public static final Item MAP = register(new MapItem("map", builder())); public static final Item GOLDEN_CARROT = register(new Item("golden_carrot", builder())); - public static final Item SKELETON_SKULL = register(new BlockItem(builder(), Blocks.SKELETON_SKULL, Blocks.SKELETON_WALL_SKULL)); - public static final Item WITHER_SKELETON_SKULL = register(new BlockItem(builder(), Blocks.WITHER_SKELETON_SKULL, Blocks.WITHER_SKELETON_WALL_SKULL)); - public static final Item PLAYER_HEAD = register(new PlayerHeadItem(builder(), Blocks.PLAYER_HEAD, Blocks.PLAYER_WALL_HEAD)); - public static final Item ZOMBIE_HEAD = register(new BlockItem(builder(), Blocks.ZOMBIE_HEAD, Blocks.ZOMBIE_WALL_HEAD)); - public static final Item CREEPER_HEAD = register(new BlockItem(builder(), Blocks.CREEPER_HEAD, Blocks.CREEPER_WALL_HEAD)); - public static final Item DRAGON_HEAD = register(new BlockItem(builder(), Blocks.DRAGON_HEAD, Blocks.DRAGON_WALL_HEAD)); - public static final Item PIGLIN_HEAD = register(new BlockItem(builder(), Blocks.PIGLIN_HEAD, Blocks.PIGLIN_WALL_HEAD)); - public static final Item NETHER_STAR = register(new Item("nether_star", builder())); + public static final Item SKELETON_SKULL = register(new BlockItem(builder().rarity(Rarity.UNCOMMON), Blocks.SKELETON_SKULL, Blocks.SKELETON_WALL_SKULL)); + public static final Item WITHER_SKELETON_SKULL = register(new BlockItem(builder().rarity(Rarity.UNCOMMON), Blocks.WITHER_SKELETON_SKULL, Blocks.WITHER_SKELETON_WALL_SKULL)); + public static final Item PLAYER_HEAD = register(new PlayerHeadItem(builder().rarity(Rarity.UNCOMMON), Blocks.PLAYER_HEAD, Blocks.PLAYER_WALL_HEAD)); + public static final Item ZOMBIE_HEAD = register(new BlockItem(builder().rarity(Rarity.UNCOMMON), Blocks.ZOMBIE_HEAD, Blocks.ZOMBIE_WALL_HEAD)); + public static final Item CREEPER_HEAD = register(new BlockItem(builder().rarity(Rarity.UNCOMMON), Blocks.CREEPER_HEAD, Blocks.CREEPER_WALL_HEAD)); + public static final Item DRAGON_HEAD = register(new BlockItem(builder().rarity(Rarity.UNCOMMON), Blocks.DRAGON_HEAD, Blocks.DRAGON_WALL_HEAD)); + public static final Item PIGLIN_HEAD = register(new BlockItem(builder().rarity(Rarity.UNCOMMON), Blocks.PIGLIN_HEAD, Blocks.PIGLIN_WALL_HEAD)); + public static final Item NETHER_STAR = register(new Item("nether_star", builder().rarity(Rarity.UNCOMMON))); public static final Item PUMPKIN_PIE = register(new Item("pumpkin_pie", builder())); public static final Item FIREWORK_ROCKET = register(new FireworkRocketItem("firework_rocket", builder())); public static final Item FIREWORK_STAR = register(new FireworkStarItem("firework_star", builder())); - public static final Item ENCHANTED_BOOK = register(new EnchantedBookItem("enchanted_book", builder().stackSize(1))); + public static final Item ENCHANTED_BOOK = register(new EnchantedBookItem("enchanted_book", builder().stackSize(1).rarity(Rarity.UNCOMMON))); public static final Item NETHER_BRICK = register(new Item("nether_brick", builder())); public static final Item PRISMARINE_SHARD = register(new Item("prismarine_shard", builder())); public static final Item PRISMARINE_CRYSTALS = register(new Item("prismarine_crystals", builder())); @@ -1167,7 +1168,7 @@ public final class Items { 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))); + public static final Item COMMAND_BLOCK_MINECART = register(new Item("command_block_minecart", builder().stackSize(1).rarity(Rarity.EPIC))); public static final Item MUTTON = register(new Item("mutton", builder())); public static final Item COOKED_MUTTON = register(new Item("cooked_mutton", builder())); public static final Item WHITE_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.WHITE_BANNER, Blocks.WHITE_WALL_BANNER)); @@ -1186,7 +1187,7 @@ public final class Items { public static final Item GREEN_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.GREEN_BANNER, Blocks.GREEN_WALL_BANNER)); public static final Item RED_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.RED_BANNER, Blocks.RED_WALL_BANNER)); public static final Item BLACK_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.BLACK_BANNER, Blocks.BLACK_WALL_BANNER)); - public static final Item END_CRYSTAL = register(new Item("end_crystal", builder())); + public static final Item END_CRYSTAL = register(new Item("end_crystal", builder().rarity(Rarity.RARE))); public static final Item CHORUS_FRUIT = register(new Item("chorus_fruit", builder())); public static final Item POPPED_CHORUS_FRUIT = register(new Item("popped_chorus_fruit", builder())); public static final Item TORCHFLOWER_SEEDS = register(new BlockItem("torchflower_seeds", builder(), Blocks.TORCHFLOWER_CROP)); @@ -1194,52 +1195,52 @@ public final class Items { public static final Item BEETROOT = register(new Item("beetroot", builder())); public static final Item BEETROOT_SEEDS = register(new BlockItem("beetroot_seeds", builder(), Blocks.BEETROOTS)); public static final Item BEETROOT_SOUP = register(new Item("beetroot_soup", builder().stackSize(1))); - public static final Item DRAGON_BREATH = register(new Item("dragon_breath", builder())); + public static final Item DRAGON_BREATH = register(new Item("dragon_breath", builder().rarity(Rarity.UNCOMMON))); public static final Item SPLASH_POTION = register(new PotionItem("splash_potion", builder().stackSize(1))); public static final Item SPECTRAL_ARROW = register(new Item("spectral_arrow", builder())); public static final Item TIPPED_ARROW = register(new TippedArrowItem("tipped_arrow", builder())); public static final Item LINGERING_POTION = register(new PotionItem("lingering_potion", builder().stackSize(1))); public static final Item SHIELD = register(new ShieldItem("shield", builder().stackSize(1).maxDamage(336))); - public static final Item TOTEM_OF_UNDYING = register(new Item("totem_of_undying", builder().stackSize(1))); + public static final Item TOTEM_OF_UNDYING = register(new Item("totem_of_undying", builder().stackSize(1).rarity(Rarity.UNCOMMON))); public static final Item SHULKER_SHELL = register(new Item("shulker_shell", builder())); public static final Item IRON_NUGGET = register(new Item("iron_nugget", builder())); - public static final Item KNOWLEDGE_BOOK = register(new Item("knowledge_book", builder().stackSize(1))); - public static final Item DEBUG_STICK = register(new Item("debug_stick", builder().stackSize(1))); - public static final Item MUSIC_DISC_13 = register(new Item("music_disc_13", builder().stackSize(1))); - public static final Item MUSIC_DISC_CAT = register(new Item("music_disc_cat", builder().stackSize(1))); - public static final Item MUSIC_DISC_BLOCKS = register(new Item("music_disc_blocks", builder().stackSize(1))); - public static final Item MUSIC_DISC_CHIRP = register(new Item("music_disc_chirp", builder().stackSize(1))); - public static final Item MUSIC_DISC_CREATOR = register(new Item("music_disc_creator", builder().stackSize(1))); - public static final Item MUSIC_DISC_CREATOR_MUSIC_BOX = register(new Item("music_disc_creator_music_box", builder().stackSize(1))); - public static final Item MUSIC_DISC_FAR = register(new Item("music_disc_far", builder().stackSize(1))); - public static final Item MUSIC_DISC_MALL = register(new Item("music_disc_mall", builder().stackSize(1))); - public static final Item MUSIC_DISC_MELLOHI = register(new Item("music_disc_mellohi", builder().stackSize(1))); - public static final Item MUSIC_DISC_STAL = register(new Item("music_disc_stal", builder().stackSize(1))); - public static final Item MUSIC_DISC_STRAD = register(new Item("music_disc_strad", builder().stackSize(1))); - public static final Item MUSIC_DISC_WARD = register(new Item("music_disc_ward", builder().stackSize(1))); - public static final Item MUSIC_DISC_11 = register(new Item("music_disc_11", builder().stackSize(1))); - public static final Item MUSIC_DISC_WAIT = register(new Item("music_disc_wait", builder().stackSize(1))); - public static final Item MUSIC_DISC_OTHERSIDE = register(new Item("music_disc_otherside", builder().stackSize(1))); - public static final Item MUSIC_DISC_RELIC = register(new Item("music_disc_relic", builder().stackSize(1))); - 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 MUSIC_DISC_PRECIPICE = register(new Item("music_disc_precipice", builder().stackSize(1))); + public static final Item KNOWLEDGE_BOOK = register(new Item("knowledge_book", builder().stackSize(1).rarity(Rarity.EPIC))); + public static final Item DEBUG_STICK = register(new Item("debug_stick", builder().stackSize(1).rarity(Rarity.EPIC).glint(true))); + public static final Item MUSIC_DISC_13 = register(new Item("music_disc_13", builder().stackSize(1).rarity(Rarity.RARE))); + public static final Item MUSIC_DISC_CAT = register(new Item("music_disc_cat", builder().stackSize(1).rarity(Rarity.RARE))); + public static final Item MUSIC_DISC_BLOCKS = register(new Item("music_disc_blocks", builder().stackSize(1).rarity(Rarity.RARE))); + public static final Item MUSIC_DISC_CHIRP = register(new Item("music_disc_chirp", builder().stackSize(1).rarity(Rarity.RARE))); + public static final Item MUSIC_DISC_CREATOR = register(new Item("music_disc_creator", builder().stackSize(1).rarity(Rarity.RARE))); + public static final Item MUSIC_DISC_CREATOR_MUSIC_BOX = register(new Item("music_disc_creator_music_box", builder().stackSize(1).rarity(Rarity.RARE))); + public static final Item MUSIC_DISC_FAR = register(new Item("music_disc_far", builder().stackSize(1).rarity(Rarity.RARE))); + public static final Item MUSIC_DISC_MALL = register(new Item("music_disc_mall", builder().stackSize(1).rarity(Rarity.RARE))); + public static final Item MUSIC_DISC_MELLOHI = register(new Item("music_disc_mellohi", builder().stackSize(1).rarity(Rarity.RARE))); + public static final Item MUSIC_DISC_STAL = register(new Item("music_disc_stal", builder().stackSize(1).rarity(Rarity.RARE))); + public static final Item MUSIC_DISC_STRAD = register(new Item("music_disc_strad", builder().stackSize(1).rarity(Rarity.RARE))); + public static final Item MUSIC_DISC_WARD = register(new Item("music_disc_ward", builder().stackSize(1).rarity(Rarity.RARE))); + public static final Item MUSIC_DISC_11 = register(new Item("music_disc_11", builder().stackSize(1).rarity(Rarity.RARE))); + public static final Item MUSIC_DISC_WAIT = register(new Item("music_disc_wait", builder().stackSize(1).rarity(Rarity.RARE))); + public static final Item MUSIC_DISC_OTHERSIDE = register(new Item("music_disc_otherside", builder().stackSize(1).rarity(Rarity.RARE))); + public static final Item MUSIC_DISC_RELIC = register(new Item("music_disc_relic", builder().stackSize(1).rarity(Rarity.RARE))); + public static final Item MUSIC_DISC_5 = register(new Item("music_disc_5", builder().stackSize(1).rarity(Rarity.RARE))); + public static final Item MUSIC_DISC_PIGSTEP = register(new Item("music_disc_pigstep", builder().stackSize(1).rarity(Rarity.RARE))); + public static final Item MUSIC_DISC_PRECIPICE = register(new Item("music_disc_precipice", builder().stackSize(1).rarity(Rarity.RARE))); 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).attackDamage(9.0))); + public static final Item TRIDENT = register(new Item("trident", builder().stackSize(1).maxDamage(250).attackDamage(9.0).rarity(Rarity.EPIC))); 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())); + public static final Item HEART_OF_THE_SEA = register(new Item("heart_of_the_sea", builder().rarity(Rarity.UNCOMMON))); public static final Item CROSSBOW = register(new CrossbowItem("crossbow", builder().stackSize(1).maxDamage(465))); public static final Item SUSPICIOUS_STEW = register(new Item("suspicious_stew", builder().stackSize(1))); public static final Item LOOM = register(new BlockItem(builder(), Blocks.LOOM)); public static final Item FLOWER_BANNER_PATTERN = register(new Item("flower_banner_pattern", builder().stackSize(1))); - public static final Item CREEPER_BANNER_PATTERN = register(new Item("creeper_banner_pattern", builder().stackSize(1))); - public static final Item SKULL_BANNER_PATTERN = register(new Item("skull_banner_pattern", builder().stackSize(1))); - public static final Item MOJANG_BANNER_PATTERN = register(new Item("mojang_banner_pattern", builder().stackSize(1))); + public static final Item CREEPER_BANNER_PATTERN = register(new Item("creeper_banner_pattern", builder().stackSize(1).rarity(Rarity.UNCOMMON))); + public static final Item SKULL_BANNER_PATTERN = register(new Item("skull_banner_pattern", builder().stackSize(1).rarity(Rarity.UNCOMMON))); + public static final Item MOJANG_BANNER_PATTERN = register(new Item("mojang_banner_pattern", builder().stackSize(1).rarity(Rarity.EPIC))); 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 PIGLIN_BANNER_PATTERN = register(new Item("piglin_banner_pattern", builder().stackSize(1).rarity(Rarity.UNCOMMON))); + public static final Item FLOW_BANNER_PATTERN = register(new Item("flow_banner_pattern", builder().stackSize(1).rarity(Rarity.RARE))); + public static final Item GUSTER_BANNER_PATTERN = register(new Item("guster_banner_pattern", builder().stackSize(1).rarity(Rarity.RARE))); public static final Item GOAT_HORN = register(new GoatHornItem("goat_horn", builder().stackSize(1))); public static final Item COMPOSTER = register(new BlockItem(builder(), Blocks.COMPOSTER)); public static final Item BARREL = register(new BlockItem(builder(), Blocks.BARREL)); diff --git a/core/src/main/java/org/geysermc/geyser/item/components/Rarity.java b/core/src/main/java/org/geysermc/geyser/item/components/Rarity.java new file mode 100644 index 000000000..6fa74ea35 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/item/components/Rarity.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 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.components; + +import lombok.Getter; + +@Getter +public enum Rarity { + COMMON("common", 'f'), + UNCOMMON("uncommon", 'e'), + RARE("rare", 'b'), + EPIC("epic", 'd'); + + private final String name; + private final char color; + + Rarity(final String name, char chatColor) { + this.name = name; + this.color = chatColor; + } + + private static final Rarity[] VALUES = values(); + + public static Rarity fromId(int id) { + return VALUES.length > id ? VALUES[id] : VALUES[0]; + } + +} 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 362b760c7..57538565a 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 @@ -35,6 +35,7 @@ import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.item.BedrockEnchantment; import org.geysermc.geyser.item.Items; +import org.geysermc.geyser.item.components.Rarity; import org.geysermc.geyser.item.enchantment.Enchantment; import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.registry.type.ItemMapping; @@ -63,12 +64,16 @@ public class Item { private final int stackSize; private final int attackDamage; private final int maxDamage; + private final Rarity rarity; + private final boolean glint; public Item(String javaIdentifier, Builder builder) { this.javaIdentifier = MinecraftKey.key(javaIdentifier).asString().intern(); this.stackSize = builder.stackSize; this.maxDamage = builder.maxDamage; this.attackDamage = builder.attackDamage; + this.rarity = builder.rarity; + this.glint = builder.glint; } public String javaIdentifier() { @@ -91,6 +96,14 @@ public class Item { return stackSize; } + public Rarity rarity() { + return rarity; + } + + public boolean glint() { + return glint; + } + public boolean isValidRepairItem(Item other) { return false; } @@ -275,6 +288,8 @@ public class Item { private int stackSize = 64; private int maxDamage; private int attackDamage; + private Rarity rarity = Rarity.COMMON; + private boolean glint = false; public Builder stackSize(int stackSize) { this.stackSize = stackSize; @@ -292,6 +307,16 @@ public class Item { return this; } + public Builder rarity(Rarity rarity) { + this.rarity = rarity; + return this; + } + + public Builder glint(boolean glintOverride) { + this.glint = glintOverride; + return this; + } + private Builder() { } } 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 85207ac3a..2d26d14f8 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 @@ -58,6 +58,7 @@ 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.components.Rarity; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; @@ -399,8 +400,9 @@ public class ItemRegistryPopulator { } } - if (javaOnlyItems.contains(javaItem)) { + if (javaOnlyItems.contains(javaItem) || javaItem.rarity() != Rarity.COMMON) { // These items don't exist on Bedrock, so set up a variable that indicates they should have custom names + // Or, ensure that we are translating these at all times to account for rarity colouring mappingBuilder = mappingBuilder.translationString((bedrockBlock != null ? "block." : "item.") + entry.getKey().replace(":", ".")); GeyserImpl.getInstance().getLogger().debug("Adding " + entry.getKey() + " as an item that needs to be translated."); } 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 abe39f177..6a781dcb8 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 @@ -33,7 +33,9 @@ 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.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; @@ -41,6 +43,7 @@ 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.components.Rarity; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.registry.BlockRegistries; @@ -145,7 +148,20 @@ public final class ItemTranslator { if (components.get(DataComponentType.HIDE_TOOLTIP) != null) hideTooltips = true; } - String customName = getCustomName(session, components, bedrockItem); + Rarity rarity = javaItem.rarity(); + boolean enchantmentGlint = javaItem.glint(); + if (components != null) { + Integer rarityIndex = components.get(DataComponentType.RARITY); + if (rarityIndex != null) { + rarity = Rarity.fromId(rarityIndex); + } + Boolean enchantmentGlintOverride = components.get(DataComponentType.ENCHANTMENT_GLINT_OVERRIDE); + if (enchantmentGlintOverride != null) { + enchantmentGlint = enchantmentGlintOverride; + } + } + + String customName = getCustomName(session, components, bedrockItem, rarity.getColor()); if (customName != null) { nbtBuilder.setCustomName(customName); } @@ -162,6 +178,12 @@ public final class ItemTranslator { addAdvancedTooltips(components, nbtBuilder, javaItem, session.locale()); } + // Add enchantment override. We can't remove it - enchantments would stop showing - but we can add it. + if (enchantmentGlint) { + NbtMapBuilder nbtMapBuilder = nbtBuilder.getOrCreateNbt(); + nbtMapBuilder.putIfAbsent("ench", NbtList.EMPTY); + } + ItemData.Builder builder = javaItem.translateToBedrock(count, components, bedrockItem, session.getItemMappings()); // Finalize the Bedrock NBT builder.tag(nbtBuilder.build()); @@ -401,16 +423,6 @@ public final class ItemTranslator { } } - /** - * Translates the display name of the item - * @param session the Bedrock client's session - * @param components the components to translate - * @param mapping the item entry, in case it requires translation - */ - 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. From 6e0bad3c40605c4ac2f3cbac7c6af673f679ead5 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sat, 13 Jul 2024 15:11:22 -0400 Subject: [PATCH 153/233] Fix #4837 by not hardcoding dimension IDs --- .../living/monster/EnderDragonEntity.java | 8 +- .../geysermc/geyser/level/JavaDimension.java | 22 ++- .../geyser/session/GeyserSession.java | 2 - .../protocol/java/JavaLoginTranslator.java | 17 +- .../protocol/java/JavaRespawnTranslator.java | 11 +- .../java/entity/JavaAnimateTranslator.java | 2 +- .../java/level/JavaLevelEventTranslator.java | 3 +- .../level/JavaLevelParticlesTranslator.java | 2 +- .../java/level/JavaMapItemDataTranslator.java | 2 +- ...JavaSetDefaultSpawnPositionTranslator.java | 2 +- .../org/geysermc/geyser/util/ChunkUtils.java | 5 +- .../geysermc/geyser/util/DimensionUtils.java | 157 ++++++++++-------- 12 files changed, 135 insertions(+), 98 deletions(-) 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 0162d498e..04044fcb4 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 @@ -30,7 +30,11 @@ 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.*; +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.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.type.Tickable; import org.geysermc.geyser.entity.type.living.MobEntity; @@ -260,7 +264,7 @@ public class EnderDragonEntity extends MobEntity implements Tickable { // so we need to manually spawn particles for (int i = 0; i < 8; i++) { SpawnParticleEffectPacket spawnParticleEffectPacket = new SpawnParticleEffectPacket(); - spawnParticleEffectPacket.setDimensionId(DimensionUtils.javaToBedrock(session.getDimension())); + spawnParticleEffectPacket.setDimensionId(DimensionUtils.javaToBedrock(session)); spawnParticleEffectPacket.setPosition(head.getPosition().add(random.nextGaussian() / 2f, random.nextGaussian() / 2f, random.nextGaussian() / 2f)); spawnParticleEffectPacket.setIdentifier("minecraft:dragon_breath_fire"); spawnParticleEffectPacket.setMolangVariablesJson(Optional.empty()); 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 dd0f4215e..7462844fc 100644 --- a/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java +++ b/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java @@ -25,15 +25,17 @@ package org.geysermc.geyser.level; +import net.kyori.adventure.key.Key; import org.cloudburstmc.nbt.NbtMap; import org.geysermc.geyser.session.cache.registry.RegistryEntryContext; +import org.geysermc.geyser.util.DimensionUtils; /** * Represents the information we store from the current Java dimension * @param piglinSafe Whether piglins and hoglins are safe from conversion in this dimension. * This controls if they have the shaking effect applied in the dimension. */ -public record JavaDimension(int minY, int maxY, boolean piglinSafe, double worldCoordinateScale) { +public record JavaDimension(int minY, int maxY, boolean piglinSafe, double worldCoordinateScale, int bedrockId, boolean isNetherLike) { public static JavaDimension read(RegistryEntryContext entry) { NbtMap dimension = entry.data(); @@ -46,6 +48,22 @@ public record JavaDimension(int minY, int maxY, boolean piglinSafe, double world // Load world coordinate scale for the world border double coordinateScale = dimension.getDouble("coordinate_scale"); - return new JavaDimension(minY, maxY, piglinSafe, coordinateScale); + boolean isNetherLike; + // Cache the Bedrock version of this dimension, and base it off the ID - THE ID CAN CHANGE!!! + // https://github.com/GeyserMC/Geyser/issues/4837 + int bedrockId; + Key id = entry.id(); + if ("minecraft".equals(id.namespace())) { + String identifier = id.asString(); + bedrockId = DimensionUtils.javaToBedrock(identifier); + isNetherLike = DimensionUtils.NETHER_IDENTIFIER.equals(identifier); + } else { + // Effects should give is a clue on how this (custom) dimension is supposed to look like + String effects = dimension.getString("effects"); + bedrockId = DimensionUtils.javaToBedrock(effects); + isNetherLike = DimensionUtils.NETHER_IDENTIFIER.equals(effects); + } + + return new JavaDimension(minY, maxY, piglinSafe, coordinateScale, bedrockId, isNetherLike); } } 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 25dd21662..3d47956b9 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -312,8 +312,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { * The dimension of the player. * As all entities are in the same world, this can be safely applied to all other entities. */ - @Setter - private int dimension = DimensionUtils.OVERWORLD; @MonotonicNonNull @Setter private JavaDimension dimensionType = null; 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 6988d6cc8..1e885403b 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 @@ -27,6 +27,7 @@ package org.geysermc.geyser.translator.protocol.java; import net.kyori.adventure.key.Key; import org.geysermc.erosion.Constants; +import org.geysermc.geyser.level.JavaDimension; import org.geysermc.geyser.util.MinecraftKey; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerSpawnInfo; import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundCustomPayloadPacket; @@ -65,12 +66,15 @@ public class JavaLoginTranslator extends PacketTranslator { SpawnParticleEffectPacket stringPacket = new SpawnParticleEffectPacket(); stringPacket.setIdentifier(particleMapping.identifier()); 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 1591b4952..52a08ab29 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 @@ -46,7 +46,7 @@ public class JavaMapItemDataTranslator extends PacketTranslator entityEffects = session.getEffectCache().getEntityEffects(); + for (Effect effect : entityEffects) { + MobEffectPacket mobEffectPacket = new MobEffectPacket(); + mobEffectPacket.setEvent(MobEffectPacket.Event.REMOVE); + mobEffectPacket.setRuntimeEntityId(player.getGeyserId()); + mobEffectPacket.setEffectId(EntityUtils.toBedrockEffectId(effect)); + session.sendUpstreamPacket(mobEffectPacket); + } + // Effects are re-sent from server + entityEffects.clear(); + + finalizeDimensionSwitch(session, player); + + // If the bedrock nether height workaround is enabled, meaning the client is told it's in the end dimension, + // 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 (javaDimension.isNetherLike()) { + session.camera().sendFog(BEDROCK_FOG_HELL); + } else if (previousDimension.isNetherLike()) { + session.camera().removeFog(BEDROCK_FOG_HELL); + } + } + } + + /** + * Switch dimensions without clearing internal logic. + */ + public static void fastSwitchDimension(GeyserSession session, int bedrockDimension) { + changeDimension(session, bedrockDimension); + finalizeDimensionSwitch(session, session.getPlayerEntity()); + } + + private static void changeDimension(GeyserSession session, int bedrockDimension) { if (session.getServerRenderDistance() > 32 && !session.isEmulatePost1_13Logic()) { // The server-sided view distance wasn't a thing until Minecraft Java 1.14 // So ViaVersion compensates by sending a "view distance" of 64 @@ -77,7 +116,7 @@ public class DimensionUtils { // To solve this, we cap at 32 unless we know that the render distance actually exceeds 32 // Also, as of 1.19: PS4 crashes with a ChunkRadiusUpdatedPacket too large session.getGeyser().getLogger().debug("Applying dimension switching workaround for Bedrock render distance of " - + session.getServerRenderDistance()); + + session.getServerRenderDistance()); ChunkRadiusUpdatedPacket chunkRadiusUpdatedPacket = new ChunkRadiusUpdatedPacket(); chunkRadiusUpdatedPacket.setRadius(32); session.sendUpstreamPacket(chunkRadiusUpdatedPacket); @@ -92,24 +131,14 @@ public class DimensionUtils { changeDimensionPacket.setPosition(pos); session.sendUpstreamPacket(changeDimensionPacket); - session.setDimension(javaDimension); - setBedrockDimension(session, javaDimension); + setBedrockDimension(session, bedrockDimension); - player.setPosition(pos); + session.getPlayerEntity().setPosition(pos); session.setSpawned(false); session.setLastChunkPosition(null); + } - Set entityEffects = session.getEffectCache().getEntityEffects(); - for (Effect effect : entityEffects) { - MobEffectPacket mobEffectPacket = new MobEffectPacket(); - mobEffectPacket.setEvent(MobEffectPacket.Event.REMOVE); - mobEffectPacket.setRuntimeEntityId(player.getGeyserId()); - mobEffectPacket.setEffectId(EntityUtils.toBedrockEffectId(effect)); - session.sendUpstreamPacket(mobEffectPacket); - } - // Effects are re-sent from server - entityEffects.clear(); - + private static void finalizeDimensionSwitch(GeyserSession session, Entity player) { //let java server handle portal travel sound StopSoundPacket stopSoundPacket = new StopSoundPacket(); stopSoundPacket.setStoppingAllSound(true); @@ -130,23 +159,12 @@ public class DimensionUtils { // TODO - fix this hack of a fix by sending the final dimension switching logic after sections have been sent. // The client wants sections sent to it before it can successfully respawn. ChunkUtils.sendEmptyChunks(session, player.getPosition().toInt(), 3, true); - - // If the bedrock nether height workaround is enabled, meaning the client is told it's in the end dimension, - // 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 == javaDimension) { - session.camera().sendFog(BEDROCK_FOG_HELL); - } else if (NETHER == previousDimension) { - session.camera().removeFog(BEDROCK_FOG_HELL); - } - } } - 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; + public static void setBedrockDimension(GeyserSession session, int bedrockDimension) { + session.getChunkCache().setBedrockDimension(switch (bedrockDimension) { + case BEDROCK_END_ID -> BedrockDimension.THE_END; + case BEDROCK_DEFAULT_NETHER_ID -> BedrockDimension.THE_NETHER; // JavaDimension *should* be set to BEDROCK_END_ID if the Nether workaround is enabled. default -> BedrockDimension.OVERWORLD; }); } @@ -155,26 +173,12 @@ public class DimensionUtils { if (dimension == BedrockDimension.THE_NETHER) { return BEDROCK_NETHER_ID; } else if (dimension == BedrockDimension.THE_END) { - return 2; + return BEDROCK_END_ID; } else { - return 0; + return BEDROCK_OVERWORLD_ID; } } - /** - * 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(int javaDimension) { - return switch (javaDimension) { - case NETHER -> BEDROCK_NETHER_ID; - case THE_END -> 2; - default -> 0; - }; - } - /** * Map the Java edition dimension IDs to Bedrock edition * @@ -183,12 +187,23 @@ public class DimensionUtils { */ public static int javaToBedrock(String javaDimension) { return switch (javaDimension) { - case "minecraft:the_nether" -> BEDROCK_NETHER_ID; + case NETHER_IDENTIFIER -> BEDROCK_NETHER_ID; case "minecraft:the_end" -> 2; default -> 0; }; } + /** + * Gets the Bedrock dimension ID, with a safety check if a packet is created before the player is logged/spawned in. + */ + public static int javaToBedrock(GeyserSession session) { + JavaDimension dimension = session.getDimensionType(); + if (dimension == null) { + return BEDROCK_OVERWORLD_ID; + } + return dimension.bedrockId(); + } + /** * 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. @@ -197,28 +212,28 @@ public class DimensionUtils { */ public static void changeBedrockNetherId(boolean isAboveNetherBedrockBuilding) { // Change dimension ID to the End to allow for building above Bedrock - BEDROCK_NETHER_ID = isAboveNetherBedrockBuilding ? 2 : 1; + BEDROCK_NETHER_ID = isAboveNetherBedrockBuilding ? BEDROCK_END_ID : BEDROCK_DEFAULT_NETHER_ID; } /** * Gets the fake, temporary dimension we send clients to so we aren't switching to the same dimension without an additional * dimension switch. * - * @param currentDimension the current dimension of the player - * @param newDimension the new dimension that the player will be transferred to - * @return the fake dimension to transfer to + * @param currentBedrockDimension the current dimension of the player + * @param newBedrockDimension the new dimension that the player will be transferred to + * @return the Bedrock fake dimension to transfer to */ - public static int getTemporaryDimension(int currentDimension, int newDimension) { + public static int getTemporaryDimension(int currentBedrockDimension, int newBedrockDimension) { if (isCustomBedrockNetherId()) { // Prevents rare instances of Bedrock locking up - return javaToBedrock(newDimension) == 2 ? OVERWORLD : NETHER; + return newBedrockDimension == BEDROCK_END_ID ? BEDROCK_OVERWORLD_ID : BEDROCK_END_ID; } // Check current Bedrock dimension and not just the Java dimension. // Fixes rare instances like https://github.com/GeyserMC/Geyser/issues/3161 - return javaToBedrock(currentDimension) == 0 ? NETHER : OVERWORLD; + return currentBedrockDimension == BEDROCK_OVERWORLD_ID ? BEDROCK_DEFAULT_NETHER_ID : BEDROCK_OVERWORLD_ID; } public static boolean isCustomBedrockNetherId() { - return BEDROCK_NETHER_ID == 2; + return BEDROCK_NETHER_ID == BEDROCK_END_ID; } } From 6ab0186fc9e7753fc15620d2a9eba57fc0b76ab0 Mon Sep 17 00:00:00 2001 From: chris Date: Sat, 13 Jul 2024 22:00:15 +0200 Subject: [PATCH 154/233] Fix: Manually translated item names for block items not showing up properly (#4857) --- .../geyser/registry/populator/ItemRegistryPopulator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 2d26d14f8..aad5e494d 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 @@ -59,6 +59,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.components.Rarity; +import org.geysermc.geyser.item.type.BlockItem; import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; @@ -403,7 +404,7 @@ public class ItemRegistryPopulator { if (javaOnlyItems.contains(javaItem) || javaItem.rarity() != Rarity.COMMON) { // These items don't exist on Bedrock, so set up a variable that indicates they should have custom names // Or, ensure that we are translating these at all times to account for rarity colouring - mappingBuilder = mappingBuilder.translationString((bedrockBlock != null ? "block." : "item.") + entry.getKey().replace(":", ".")); + mappingBuilder = mappingBuilder.translationString((javaItem instanceof BlockItem ? "block." : "item.") + entry.getKey().replace(":", ".")); GeyserImpl.getInstance().getLogger().debug("Adding " + entry.getKey() + " as an item that needs to be translated."); } From 49f66c2a022b67a48f300fa652062241046f5eb9 Mon Sep 17 00:00:00 2001 From: LetsGoAway <68365423+letsgoawaydev@users.noreply.github.com> Date: Sun, 14 Jul 2024 16:44:39 +0800 Subject: [PATCH 155/233] Correctly cap scale attribute (#4856) * Fix scale attribute cap * Update LivingEntity.java --- .../geysermc/geyser/entity/attribute/GeyserAttributeType.java | 2 +- .../java/org/geysermc/geyser/entity/type/LivingEntity.java | 3 ++- 2 files changed, 3 insertions(+), 2 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 f19912a8c..a4a0df8b8 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,7 +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? + SCALE("minecraft:generic.scale", null, 0.0625f, 16f, 1f), // 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 499084555..2a1bc1188 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 @@ -48,6 +48,7 @@ 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.geyser.util.MathUtils; 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; @@ -252,7 +253,7 @@ public class LivingEntity extends Entity { } private void setAttributeScale(float scale) { - this.attributeScale = scale; + this.attributeScale = MathUtils.clamp(scale, GeyserAttributeType.SCALE.getMinimum(), GeyserAttributeType.SCALE.getMaximum()); applyScale(); } From 9cdda707a31d299a24dcff8081fc306c69902e7b Mon Sep 17 00:00:00 2001 From: chris Date: Sun, 14 Jul 2024 20:17:22 +0200 Subject: [PATCH 156/233] Fix: Send a container close packet to Java for containers that could not be opened (#4861) * Close containers if we did not manage to open it * Mark session inventory translator as nonnull --- .../java/org/geysermc/geyser/session/GeyserSession.java | 2 +- .../protocol/java/inventory/JavaOpenBookTranslator.java | 1 + .../main/java/org/geysermc/geyser/util/InventoryUtils.java | 7 ++++++- 3 files changed, 8 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 25dd21662..c2f94b1c6 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -222,7 +222,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { private boolean closingInventory; @Setter - private InventoryTranslator inventoryTranslator = InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR; + private @NonNull InventoryTranslator inventoryTranslator = InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR; /** * Use {@link #getNextItemNetId()} instead for consistency 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 e7cf21a69..172880725 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 @@ -70,6 +70,7 @@ public class JavaOpenBookTranslator extends PacketTranslator { Inventory openInv = session.getOpenInventory(); @@ -110,7 +111,11 @@ public class InventoryUtils { inventory.setDisplayed(true); } } else { + // Can occur if we e.g. did not find a spot to put a fake container in + ServerboundContainerClosePacket closePacket = new ServerboundContainerClosePacket(inventory.getJavaId()); + session.sendDownstreamGamePacket(closePacket); session.setOpenInventory(null); + session.setInventoryTranslator(InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR); } } From 06890504a2bfcdbf218a9d2c2874fa1262d91cca Mon Sep 17 00:00:00 2001 From: chris Date: Sun, 14 Jul 2024 21:55:57 +0200 Subject: [PATCH 157/233] Fix: Totem animation when playing totem effects manually (#4860) * Fix: Totem animation for manually played totem effects * Ensure we always reset the offhand correctly --- .../geyser/inventory/PlayerInventory.java | 5 ++++ .../inventory/item/StoredItemMappings.java | 2 ++ .../entity/JavaEntityEventTranslator.java | 27 ++++++++++++++++++- .../geysermc/geyser/util/InventoryUtils.java | 6 +++++ 4 files changed, 39 insertions(+), 1 deletion(-) 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 9bef4b08e..c3756d663 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/PlayerInventory.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/PlayerInventory.java @@ -29,6 +29,7 @@ import lombok.Getter; import lombok.Setter; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import org.jetbrains.annotations.Range; @@ -73,6 +74,10 @@ public class PlayerInventory extends Inventory { return items[36 + heldItemSlot]; } + public boolean eitherHandMatchesItem(@NonNull Item item) { + return getItemInHand().asItem() == item || getItemInHand(Hand.OFF_HAND).asItem() == item; + } + public void setItemInHand(@NonNull GeyserItemStack item) { if (36 + heldItemSlot > this.size) { GeyserImpl.getInstance().getLogger().debug("Held item slot was larger than expected!"); 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 05f6ba6cc..475a3e588 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 @@ -50,6 +50,7 @@ public class StoredItemMappings { private final ItemMapping milkBucket; private final ItemMapping powderSnowBucket; private final ItemMapping shield; + private final ItemMapping totem; private final ItemMapping upgradeTemplate; private final ItemMapping wheat; private final ItemMapping writableBook; @@ -66,6 +67,7 @@ public class StoredItemMappings { this.milkBucket = load(itemMappings, Items.MILK_BUCKET); this.powderSnowBucket = load(itemMappings, Items.POWDER_SNOW_BUCKET); this.shield = load(itemMappings, Items.SHIELD); + this.totem = load(itemMappings, Items.TOTEM_OF_UNDYING); 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/translator/protocol/java/entity/JavaEntityEventTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaEntityEventTranslator.java index e119d39ce..6c2e02cd3 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 @@ -29,7 +29,9 @@ 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.ContainerId; import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket; +import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket; import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEvent2Packet; import org.cloudburstmc.protocol.bedrock.packet.PlaySoundPacket; @@ -42,11 +44,15 @@ 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.item.Items; 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.entity.ClientboundEntityEventPacket; +import java.util.Collections; import java.util.concurrent.ThreadLocalRandom; @Translator(packet = ClientboundEntityEventPacket.class) @@ -154,6 +160,16 @@ public class JavaEntityEventTranslator extends PacketTranslator getTotemOfUndying() { + return protocolVersion -> ItemData.builder() + .definition(Registries.ITEMS.forVersion(protocolVersion).getStoredItems().totem().getBedrockDefinition()) + .count(1).build(); + } + /** * See {@link #findOrCreateItem(GeyserSession, String)}. This is for finding a specified {@link ItemStack}. * From efc8ba061028a2c67ea7120079fa8ce8c42ea701 Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 15 Jul 2024 01:31:03 +0200 Subject: [PATCH 158/233] Fix: Block place sounds on mod platforms (#4859) --- .../mod/mixin/server/BlockPlaceMixin.java | 79 +++++++++++++++++++ .../mod/src/main/resources/geyser.mixins.json | 1 + .../java/level/JavaBlockUpdateTranslator.java | 20 ++--- 3 files changed, 91 insertions(+), 9 deletions(-) create mode 100644 bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/mixin/server/BlockPlaceMixin.java diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/mixin/server/BlockPlaceMixin.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/mixin/server/BlockPlaceMixin.java new file mode 100644 index 000000000..98620588e --- /dev/null +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/mixin/server/BlockPlaceMixin.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 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.platform.mod.mixin.server; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockState; +import org.cloudburstmc.math.vector.Vector3f; +import org.cloudburstmc.protocol.bedrock.data.SoundEvent; +import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.session.GeyserSession; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +@Mixin(BlockItem.class) +public class BlockPlaceMixin { + + @Inject(method = "place", locals = LocalCapture.CAPTURE_FAILSOFT, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;playSound(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/core/BlockPos;Lnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FF)V")) + private void geyser$hijackPlaySound(BlockPlaceContext blockPlaceContext, CallbackInfoReturnable cir, BlockPlaceContext blockPlaceContext2, BlockState blockState, BlockPos blockPos, Level level, Player player, ItemStack itemStack, BlockState blockState2, SoundType soundType) { + if (player == null) { + return; + } + + GeyserSession session = GeyserImpl.getInstance().connectionByUuid(player.getUUID()); + if (session == null) { + return; + } + + Vector3f position = Vector3f.from( + blockPos.getX(), + blockPos.getY(), + blockPos.getZ() + ); + + LevelSoundEventPacket placeBlockSoundPacket = new LevelSoundEventPacket(); + placeBlockSoundPacket.setSound(SoundEvent.PLACE); + placeBlockSoundPacket.setPosition(position); + placeBlockSoundPacket.setBabySound(false); + placeBlockSoundPacket.setExtraData(session.getBlockMappings().getBedrockBlockId(Block.BLOCK_STATE_REGISTRY.getId(blockState2))); + placeBlockSoundPacket.setIdentifier(":"); + session.sendUpstreamPacket(placeBlockSoundPacket); + session.setLastBlockPlacePosition(null); + session.setLastBlockPlaced(null); + } +} diff --git a/bootstrap/mod/src/main/resources/geyser.mixins.json b/bootstrap/mod/src/main/resources/geyser.mixins.json index 47b2f60f3..2576e1ce6 100644 --- a/bootstrap/mod/src/main/resources/geyser.mixins.json +++ b/bootstrap/mod/src/main/resources/geyser.mixins.json @@ -4,6 +4,7 @@ "package": "org.geysermc.geyser.platform.mod.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ + "server.BlockPlaceMixin", "server.ServerConnectionListenerMixin" ], "server": [ 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 d89775662..6d5fbc113 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 @@ -28,8 +28,8 @@ package org.geysermc.geyser.translator.protocol.java.level; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket; -import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.item.type.Item; +import org.geysermc.geyser.level.WorldManager; import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; @@ -43,24 +43,27 @@ public class JavaBlockUpdateTranslator extends PacketTranslator Date: Mon, 15 Jul 2024 15:16:45 -0400 Subject: [PATCH 159/233] Indicate support for Bedrock 1.21.3 --- README.md | 2 +- .../main/java/org/geysermc/geyser/network/GameProtocol.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 14bdb17a9..9469b1bb6 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.80 - 1.21.2 and Minecraft Java 1.21 +### Currently supporting Minecraft Bedrock 1.20.80 - 1.21.3 and Minecraft Java 1.21 ## 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 c79ef365d..8f3f00021 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -73,7 +73,9 @@ public final class GameProtocol { SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v685.CODEC.toBuilder() .minecraftVersion("1.21.0/1.21.1") .build())); - SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC); + SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC.toBuilder() + .minecraftVersion("1.21.2/1.21.3") + .build()); } /** From 677a56cf6c487d7cc74e139e76057fe5ba16b84b Mon Sep 17 00:00:00 2001 From: "masel.io" Date: Tue, 16 Jul 2024 11:23:30 +0200 Subject: [PATCH 160/233] Add Timeout to CompletableFuture in GeyserBungeePingPassthrough to Prevent Memory Leak (#4858) * fix: Add timeout for GeyserBungeePingPassthrough#getPingInformation Signed-off-by: ByteExceptionM * fix: Use Geyser Logger instead of Bungee Logger Signed-off-by: ByteExceptionM * Fix typo Co-authored-by: Konicai <71294714+Konicai@users.noreply.github.com> * chore: Add ip suppression if configured Signed-off-by: ByteExceptionM * Remove empty line Co-authored-by: chris * Remove empty line Co-authored-by: chris --------- Signed-off-by: ByteExceptionM Co-authored-by: Konicai <71294714+Konicai@users.noreply.github.com> Co-authored-by: chris --- .../bungeecord/GeyserBungeePingPassthrough.java | 14 +++++++++++++- .../geyser/ping/IGeyserPingPassthrough.java | 4 ++-- 2 files changed, 15 insertions(+), 3 deletions(-) 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 3c3853ed8..1193a52b3 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 @@ -36,6 +36,7 @@ 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.GeyserImpl; import org.geysermc.geyser.ping.GeyserPingInfo; import org.geysermc.geyser.ping.IGeyserPingPassthrough; @@ -43,6 +44,7 @@ import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; @AllArgsConstructor public class GeyserBungeePingPassthrough implements IGeyserPingPassthrough, Listener { @@ -59,7 +61,17 @@ public class GeyserBungeePingPassthrough implements IGeyserPingPassthrough, List future.complete(event); } })); - ProxyPingEvent event = future.join(); + + ProxyPingEvent event; + + try { + event = future.get(100, TimeUnit.MILLISECONDS); + } catch (Throwable cause) { + String address = GeyserImpl.getInstance().getConfig().isLogPlayerIpAddresses() ? inetSocketAddress.toString() : ""; + GeyserImpl.getInstance().getLogger().error("Failed to get ping information for " + address, cause); + return null; + } + ServerPing response = event.getResponse(); return new GeyserPingInfo( response.getDescriptionComponent().toLegacyText(), 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 69ac974cc..4e60d60e4 100644 --- a/core/src/main/java/org/geysermc/geyser/ping/IGeyserPingPassthrough.java +++ b/core/src/main/java/org/geysermc/geyser/ping/IGeyserPingPassthrough.java @@ -35,10 +35,10 @@ import java.net.InetSocketAddress; public interface IGeyserPingPassthrough { /** - * Get the MOTD of the server displayed on the multiplayer screen + * Gets the ping information, including the MOTD and player count, from the server * * @param inetSocketAddress the ip address of the client pinging the server - * @return string of the MOTD + * @return the ping information */ @Nullable GeyserPingInfo getPingInformation(InetSocketAddress inetSocketAddress); From 669a76c628f6a99eb3304b3505331e1609373111 Mon Sep 17 00:00:00 2001 From: Valaphee The Meerkat <32491319+valaphee@users.noreply.github.com> Date: Tue, 16 Jul 2024 14:13:34 +0200 Subject: [PATCH 161/233] Empty player list on phase transition, despawn skulls, always reset weather (#4847) * Empty player list on transition, despawn skulls * Always reset weather --- .../geyser/session/cache/EntityCache.java | 4 ++ .../geyser/session/cache/SkullCache.java | 8 +++ ...vaFinishConfigurationPacketTranslator.java | 49 +++++++++++++++++++ .../protocol/java/JavaLoginTranslator.java | 19 ------- .../geysermc/geyser/util/DimensionUtils.java | 15 ++++++ 5 files changed, 76 insertions(+), 19 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaFinishConfigurationPacketTranslator.java 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 6524e1ddc..3affa12cf 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 @@ -141,6 +141,10 @@ public class EntityCache { return playerEntities.values(); } + public void removeAllPlayerEntities() { + playerEntities.clear(); + } + public void addBossBar(UUID uuid, BossBar bossBar) { bossBars.put(uuid, bossBar); bossBar.addBossBar(); 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 a40a1156d..0eec39b0b 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 @@ -243,8 +243,16 @@ public class SkullCache { } public void clear() { + for (Skull skull : skulls.values()) { + if (skull.entity != null) { + skull.entity.despawnEntity(); + } + } skulls.clear(); inRangeSkulls.clear(); + for (SkullPlayerEntity skull : unusedSkullEntities) { + skull.despawnEntity(); + } unusedSkullEntities.clear(); totalSkullEntities = 0; lastPlayerPosition = null; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaFinishConfigurationPacketTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaFinishConfigurationPacketTranslator.java new file mode 100644 index 000000000..8ade4a1f0 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaFinishConfigurationPacketTranslator.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 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; + +import org.cloudburstmc.protocol.bedrock.packet.PlayerListPacket; +import org.geysermc.geyser.entity.type.player.PlayerEntity; +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.configuration.clientbound.ClientboundFinishConfigurationPacket; + +@Translator(packet = ClientboundFinishConfigurationPacket.class) +public class JavaFinishConfigurationPacketTranslator extends PacketTranslator { + + @Override + public void translate(GeyserSession session, ClientboundFinishConfigurationPacket packet) { + // Clear the player list, as on Java the player list is cleared after transitioning from config to play phase + PlayerListPacket playerListPacket = new PlayerListPacket(); + playerListPacket.setAction(PlayerListPacket.Action.REMOVE); + for (PlayerEntity otherEntity : session.getEntityCache().getAllPlayerEntities()) { + playerListPacket.getEntries().add(new PlayerListPacket.Entry(otherEntity.getTabListUuid())); + } + session.sendUpstreamPacket(playerListPacket); + session.getEntityCache().removeAllPlayerEntities(); + } +} 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 6988d6cc8..6c065a392 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 @@ -79,25 +79,6 @@ public class JavaLoginTranslator extends PacketTranslator Date: Wed, 17 Jul 2024 14:21:41 -0400 Subject: [PATCH 162/233] Fix #4870 --- .../level/block/entity/CampfireBlockEntityTranslator.java | 8 +++----- 1 file changed, 3 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 fb71a84cc..703c0954c 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 @@ -42,10 +42,9 @@ public class CampfireBlockEntityTranslator extends BlockEntityTranslator { public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) { List items = javaNbt.getList("Items", NbtType.COMPOUND); if (items != null) { - int i = 1; for (NbtMap itemTag : items) { - bedrockNbt.put("Item" + i, getItem(session, itemTag)); - i++; + int slot = itemTag.getByte("Slot") + 1; + bedrockNbt.put("Item" + slot, getItem(session, itemTag)); } } } @@ -55,8 +54,7 @@ public class CampfireBlockEntityTranslator extends BlockEntityTranslator { 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 + NbtMapBuilder tagBuilder = BedrockItemBuilder.createItemNbt(mapping, tag.getInt("count"), mapping.getBedrockData()); return tagBuilder.build(); } } From 9fe3acc81cb88d613a558111bc6b8f326add300d Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 17 Jul 2024 21:44:53 +0200 Subject: [PATCH 163/233] Properly fix hanging signs (#4872) --- .../populator/CreativeItemRegistryPopulator.java | 1 - .../registry/populator/ItemRegistryPopulator.java | 11 ++++++++++- .../geysermc/geyser/registry/type/ItemMapping.java | 2 ++ 3 files changed, 12 insertions(+), 2 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 2c033edc7..8e42887ff 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 @@ -80,7 +80,6 @@ public class CreativeItemRegistryPopulator { private static ItemData.@Nullable Builder createItemData(JsonNode itemNode, BlockMappings blockMappings, Map definitions) { int count = 1; int damage = 0; - int bedrockBlockRuntimeId; NbtMap tag = null; String identifier = itemNode.get("id").textValue(); 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 aad5e494d..2c97fe13c 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 @@ -167,6 +167,7 @@ public class ItemRegistryPopulator { Map javaItemToMapping = new Object2ObjectOpenHashMap<>(); List creativeItems = new ArrayList<>(); + Set noBlockDefinitions = new ObjectOpenHashSet<>(); AtomicInteger creativeNetId = new AtomicInteger(); CreativeItemRegistryPopulator.populate(palette, definitions, itemBuilder -> { @@ -187,6 +188,9 @@ public class ItemRegistryPopulator { bedrockBlockIdOverrides.put(identifier, item.getBlockDefinition()); } } + } else { + // Item mappings should also NOT have a block definition for these. + noBlockDefinitions.add(item.getDefinition().getIdentifier()); } }); @@ -254,7 +258,12 @@ public class ItemRegistryPopulator { } else { // Try to get an example block runtime ID from the creative contents packet, for Bedrock identifier obtaining int aValidBedrockBlockId = blacklistedIdentifiers.getOrDefault(bedrockIdentifier, customBlockItemOverride != null ? customBlockItemOverride.getRuntimeId() : -1); - if (aValidBedrockBlockId != -1 || customBlockItemOverride != null) { + if (aValidBedrockBlockId == -1 && customBlockItemOverride == null) { + // Fallback + if (!noBlockDefinitions.contains(entry.getValue().getBedrockIdentifier())) { + bedrockBlock = blockMappings.getBedrockBlock(firstBlockRuntimeId); + } + } else { // As of 1.16.220, every item requires a block runtime ID attached to it. // This is mostly for identifying different blocks with the same item ID - wool, slabs, some walls. // However, in order for some visuals and crafting to work, we need to send the first matching block state 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 437b8223a..8a2c77f28 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 @@ -28,6 +28,7 @@ package org.geysermc.geyser.registry.type; import it.unimi.dsi.fastutil.Pair; import lombok.Builder; import lombok.EqualsAndHashCode; +import lombok.ToString; import lombok.Value; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; @@ -42,6 +43,7 @@ import java.util.List; @Value @Builder @EqualsAndHashCode +@ToString public class ItemMapping { public static final ItemMapping AIR = new ItemMapping( "minecraft:air", From 8fd99e1e1a01bd5b12ef8a10c4b5778fa2b4de91 Mon Sep 17 00:00:00 2001 From: LetsGoAway <68365423+letsgoawaydev@users.noreply.github.com> Date: Sat, 20 Jul 2024 18:09:22 +0800 Subject: [PATCH 164/233] Use the correct way of sending block breaking particles (#4825) --- .../player/BedrockActionTranslator.java | 197 ++++++++++-------- 1 file changed, 113 insertions(+), 84 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 6834d3190..cd1300a13 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 @@ -32,7 +32,12 @@ import org.cloudburstmc.protocol.bedrock.data.PlayerActionType; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; -import org.cloudburstmc.protocol.bedrock.packet.*; +import org.cloudburstmc.protocol.bedrock.packet.AnimatePacket; +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.geysermc.geyser.api.block.custom.CustomBlockState; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.ItemFrameEntity; @@ -52,8 +57,17 @@ 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.*; +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.entity.player.PlayerState; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundInteractPacket; +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.ServerboundPlayerCommandPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundSwingPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundUseItemOnPacket; @Translator(packet = PlayerActionPacket.class) public class BedrockActionTranslator extends PacketTranslator { @@ -70,7 +84,7 @@ public class BedrockActionTranslator extends PacketTranslator { // Respawn process is finished and the server and client are both OK with respawning. EntityEventPacket eventPacket = new EntityEventPacket(); eventPacket.setRuntimeEntityId(entity.getGeyserId()); @@ -88,16 +102,16 @@ public class BedrockActionTranslator extends PacketTranslator { if (!entity.getFlag(EntityFlag.SWIMMING)) { ServerboundPlayerCommandPacket startSwimPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.START_SPRINTING); session.sendDownstreamGamePacket(startSwimPacket); session.setSwimming(true); } - break; - case STOP_SWIMMING: + } + case STOP_SWIMMING -> { // Prevent packet spam when Bedrock players are crawling near the edge of a block if (!session.getCollisionManager().mustPlayerCrawlHere()) { ServerboundPlayerCommandPacket stopSwimPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.STOP_SPRINTING); @@ -105,56 +119,55 @@ public class BedrockActionTranslator extends PacketTranslator { // Otherwise gliding will not work in creative ServerboundPlayerAbilitiesPacket playerAbilitiesPacket = new ServerboundPlayerAbilitiesPacket(false); session.sendDownstreamGamePacket(playerAbilitiesPacket); - case STOP_GLIDE: - ServerboundPlayerCommandPacket glidePacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.START_ELYTRA_FLYING); - session.sendDownstreamGamePacket(glidePacket); - break; - case START_SNEAK: + sendPlayerGlideToggle(session, entity); + } + case STOP_GLIDE -> sendPlayerGlideToggle(session, entity); + case START_SNEAK -> { ServerboundPlayerCommandPacket startSneakPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.START_SNEAKING); session.sendDownstreamGamePacket(startSneakPacket); session.startSneaking(); - break; - case STOP_SNEAK: + } + case STOP_SNEAK -> { ServerboundPlayerCommandPacket stopSneakPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.STOP_SNEAKING); session.sendDownstreamGamePacket(stopSneakPacket); session.stopSneaking(); - break; - case START_SPRINT: + } + case START_SPRINT -> { if (!entity.getFlag(EntityFlag.SWIMMING)) { ServerboundPlayerCommandPacket startSprintPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.START_SPRINTING); session.sendDownstreamGamePacket(startSprintPacket); session.setSprinting(true); } - break; - case STOP_SPRINT: + } + case STOP_SPRINT -> { if (!entity.getFlag(EntityFlag.SWIMMING)) { ServerboundPlayerCommandPacket stopSprintPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.STOP_SPRINTING); session.sendDownstreamGamePacket(stopSprintPacket); } session.setSprinting(false); - break; - case DROP_ITEM: + } + case DROP_ITEM -> { ServerboundPlayerActionPacket dropItemPacket = new ServerboundPlayerActionPacket(PlayerAction.DROP_ITEM, - vector, Direction.VALUES[packet.getFace()], 0); + vector, Direction.VALUES[packet.getFace()], 0); session.sendDownstreamGamePacket(dropItemPacket); - break; - case STOP_SLEEP: + } + case STOP_SLEEP -> { ServerboundPlayerCommandPacket stopSleepingPacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.LEAVE_BED); session.sendDownstreamGamePacket(stopSleepingPacket); - break; - case START_BREAK: { - // Ignore START_BREAK when the player is CREATIVE to avoid Spigot receiving 2 packets it interpets as block breaking. https://github.com/GeyserMC/Geyser/issues/4021 - if (session.getGameMode() == GameMode.CREATIVE) { + } + case START_BREAK -> { + // Ignore START_BREAK when the player is CREATIVE to avoid Spigot receiving 2 packets it interpets as block breaking. https://github.com/GeyserMC/Geyser/issues/4021 + if (session.getGameMode() == GameMode.CREATIVE) { break; } - + // Start the block breaking animation int blockState = session.getGeyser().getWorldManager().getBlockAt(session, vector); LevelEventPacket startBreak = new LevelEventPacket(); @@ -180,18 +193,20 @@ public class BedrockActionTranslator extends PacketTranslator { if (session.getGameMode() == GameMode.CREATIVE) { break; } @@ -201,52 +216,48 @@ public class BedrockActionTranslator extends PacketTranslator= (breakTime+=2) * 50) { + if (timeSinceStart >= (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()); + vector, direction, session.getWorldCache().nextPredictionSequence()); session.sendDownstreamGamePacket(finishBreakingPacket); session.setBlockBreakStartTime(0); break; } } - + // Update the break time in the event that player conditions changed (jumping, effects applied) + LevelEventPacket updateBreak = new LevelEventPacket(); + updateBreak.setType(LevelEvent.BLOCK_UPDATE_BREAK); + updateBreak.setPosition(vectorFloat); updateBreak.setData((int) (65535 / breakTime)); session.sendUpstreamPacket(updateBreak); - break; - case ABORT_BREAK: + } + case ABORT_BREAK -> { if (session.getGameMode() != GameMode.CREATIVE) { // As of 1.16.210: item frame items are taken out here. // Survival also sends START_BREAK, but by attaching our process here adventure mode also works Entity itemFrameEntity = ItemFrameEntity.getItemFrameEntity(session, vector); if (itemFrameEntity != null) { ServerboundInteractPacket interactPacket = new ServerboundInteractPacket(itemFrameEntity.getEntityId(), - InteractAction.ATTACK, Hand.MAIN_HAND, session.isSneaking()); + InteractAction.ATTACK, Hand.MAIN_HAND, session.isSneaking()); session.sendDownstreamGamePacket(interactPacket); break; } @@ -260,25 +271,23 @@ public class BedrockActionTranslator extends PacketTranslator { + } + case DIMENSION_CHANGE_SUCCESS -> { //sometimes the client doesn't feel like loading PlayStatusPacket spawnPacket = new PlayStatusPacket(); spawnPacket.setStatus(PlayStatusPacket.Status.PLAYER_SPAWN); session.sendUpstreamPacket(spawnPacket); - attributesPacket = new UpdateAttributesPacket(); + UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket(); attributesPacket.setRuntimeEntityId(entity.getGeyserId()); attributesPacket.getAttributes().addAll(entity.getAttributes().values()); session.sendUpstreamPacket(attributesPacket); - break; - case JUMP: - entity.setOnGround(false); // Increase block break time while jumping - break; - case MISSED_SWING: + } + case JUMP -> entity.setOnGround(false); // Increase block break time while jumping + case MISSED_SWING -> { // Java edition sends a cooldown when hitting air. // Normally handled by BedrockLevelSoundEventTranslator, but there is no sound on Java for this. CooldownUtils.sendCooldown(session); @@ -294,18 +303,18 @@ public class BedrockActionTranslator extends PacketTranslator { // Since 1.20.30 if (session.isCanFly()) { if (session.getGameMode() == GameMode.SPECTATOR) { - // should already be flying + // should already be flying session.sendAdventureSettings(); break; } if (session.getPlayerEntity().getFlag(EntityFlag.SWIMMING) && session.getCollisionManager().isPlayerInWater()) { - // As of 1.18.1, Java Edition cannot fly while in water, but it can fly while crawling - // If this isn't present, swimming on a 1.13.2 server and then attempting to fly will put you into a flying/swimming state that is invalid on JE + // As of 1.18.1, Java Edition cannot fly while in water, but it can fly while crawling + // If this isn't present, swimming on a 1.13.2 server and then attempting to fly will put you into a flying/swimming state that is invalid on JE session.sendAdventureSettings(); break; } @@ -313,9 +322,9 @@ public class BedrockActionTranslator extends PacketTranslator { session.setFlying(false); session.sendDownstreamGamePacket(new ServerboundPlayerAbilitiesPacket(false)); - break; - case DIMENSION_CHANGE_REQUEST_OR_CREATIVE_DESTROY_BLOCK: // Used by client to get book from lecterns and items from item frame in creative mode since 1.20.70 + } + case DIMENSION_CHANGE_REQUEST_OR_CREATIVE_DESTROY_BLOCK -> { // Used by client to get book from lecterns and items from item frame in creative mode since 1.20.70 BlockState state = session.getGeyser().getWorldManager().blockAt(session, vector); - + if (state.getValue(Properties.HAS_BOOK, false)) { session.setDroppingLecternBook(true); ServerboundUseItemOnPacket blockPacket = new ServerboundUseItemOnPacket( - vector, - Direction.DOWN, - Hand.MAIN_HAND, - 0, 0, 0, - false, - session.getWorldCache().nextPredictionSequence()); + vector, + Direction.DOWN, + Hand.MAIN_HAND, + 0, 0, 0, + false, + session.getWorldCache().nextPredictionSequence()); session.sendDownstreamGamePacket(blockPacket); break; } @@ -349,10 +358,30 @@ public class BedrockActionTranslator extends PacketTranslator levelEventPacket.setType(LevelEvent.PARTICLE_BREAK_BLOCK_UP); + case DOWN -> levelEventPacket.setType(LevelEvent.PARTICLE_BREAK_BLOCK_DOWN); + case NORTH -> levelEventPacket.setType(LevelEvent.PARTICLE_BREAK_BLOCK_NORTH); + case EAST -> levelEventPacket.setType(LevelEvent.PARTICLE_BREAK_BLOCK_EAST); + case SOUTH -> levelEventPacket.setType(LevelEvent.PARTICLE_BREAK_BLOCK_SOUTH); + case WEST -> levelEventPacket.setType(LevelEvent.PARTICLE_BREAK_BLOCK_WEST); + } + levelEventPacket.setPosition(position.toFloat()); + levelEventPacket.setData(session.getBlockMappings().getBedrockBlock(blockState).getRuntimeId()); + session.sendUpstreamPacket(levelEventPacket); + } + + private void sendPlayerGlideToggle(GeyserSession session, Entity entity) { + ServerboundPlayerCommandPacket glidePacket = new ServerboundPlayerCommandPacket(entity.getEntityId(), PlayerState.START_ELYTRA_FLYING); + session.sendDownstreamGamePacket(glidePacket); + } } From f62cef7acbd8fecab28793cc9649ddba2982bffe Mon Sep 17 00:00:00 2001 From: chris Date: Sun, 21 Jul 2024 02:10:51 +0200 Subject: [PATCH 165/233] Fix: Only shutdown/close handlers in onDisable if they're nonnull (#4882) --- .../java/org/geysermc/geyser/GeyserImpl.java | 45 +++++++++++++------ 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 88cc74691..9ee182edd 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -55,7 +55,11 @@ 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.event.lifecycle.GeyserPostInitializeEvent; +import org.geysermc.geyser.api.event.lifecycle.GeyserPostReloadEvent; +import org.geysermc.geyser.api.event.lifecycle.GeyserPreInitializeEvent; +import org.geysermc.geyser.api.event.lifecycle.GeyserPreReloadEvent; +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; @@ -85,7 +89,13 @@ import org.geysermc.geyser.skin.SkinProvider; 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.geyser.util.AssetUtils; +import org.geysermc.geyser.util.CooldownUtils; +import org.geysermc.geyser.util.DimensionUtils; +import org.geysermc.geyser.util.Metrics; +import org.geysermc.geyser.util.NewsHandler; +import org.geysermc.geyser.util.VersionCheckUtils; +import org.geysermc.geyser.util.WebUtils; import org.geysermc.mcprotocollib.network.tcp.TcpSession; import java.io.File; @@ -97,11 +107,19 @@ import java.net.UnknownHostException; import java.nio.file.Path; import java.security.Key; import java.text.DecimalFormat; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; +import java.util.function.Consumer; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -645,16 +663,11 @@ public class GeyserImpl implements GeyserApi { bootstrap.getGeyserLogger().info(GeyserLocale.getLocaleStringLog("geyser.core.shutdown.kick.done")); } - scheduledThread.shutdown(); - geyserServer.shutdown(); - if (skinUploader != null) { - skinUploader.close(); - } - newsHandler.shutdown(); - - if (this.erosionUnixListener != null) { - this.erosionUnixListener.close(); - } + runIfNonNull(scheduledThread, ScheduledExecutorService::shutdown); + runIfNonNull(geyserServer, GeyserServer::shutdown); + runIfNonNull(skinUploader, FloodgateSkinUploader::close); + runIfNonNull(newsHandler, NewsHandler::shutdown); + runIfNonNull(erosionUnixListener, UnixSocketClientListener::close); Registries.RESOURCE_PACKS.get().clear(); @@ -833,6 +846,12 @@ public class GeyserImpl implements GeyserApi { } } + private void runIfNonNull(T nullable, Consumer consumer) { + if (nullable != null) { + consumer.accept(nullable); + } + } + private void scheduleRefreshTokensWrite() { scheduledThread.execute(() -> { // Ensure all writes are handled on the same thread From 96f00981df9f6f180e90349f6e9a711fcce05883 Mon Sep 17 00:00:00 2001 From: chris Date: Sun, 21 Jul 2024 02:15:38 +0200 Subject: [PATCH 166/233] Somewhat fix: firework recipe not showing up in recipe book (#4873) * Somewhat fix firework crafting * Use instanceof instead of casting --- .../item/type/BedrockRequiresTagItem.java | 36 +++++++++++++++++++ .../geyser/item/type/FireworkRocketItem.java | 36 ++++++++++++++----- .../translator/item/ItemTranslator.java | 7 ++++ .../java/JavaUpdateRecipesTranslator.java | 33 +++++++++++++---- 4 files changed, 98 insertions(+), 14 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/item/type/BedrockRequiresTagItem.java diff --git a/core/src/main/java/org/geysermc/geyser/item/type/BedrockRequiresTagItem.java b/core/src/main/java/org/geysermc/geyser/item/type/BedrockRequiresTagItem.java new file mode 100644 index 000000000..c41d14396 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/item/type/BedrockRequiresTagItem.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 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.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.translator.item.BedrockItemBuilder; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; + +public interface BedrockRequiresTagItem { + + void addRequiredNbt(GeyserSession session, @Nullable DataComponents components, BedrockItemBuilder 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 9c637afde..2e7848318 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 @@ -27,6 +27,8 @@ package org.geysermc.geyser.item.type; import it.unimi.dsi.fastutil.ints.IntArrays; 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; @@ -41,7 +43,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.item.component.Fireworks; import java.util.ArrayList; import java.util.List; -public class FireworkRocketItem extends Item { +public class FireworkRocketItem extends Item implements BedrockRequiresTagItem { public FireworkRocketItem(String javaIdentifier, Builder builder) { super(javaIdentifier, builder); } @@ -58,14 +60,16 @@ public class FireworkRocketItem extends Item { fireworksNbt.putByte("Flight", (byte) fireworks.getFlightDuration()); List explosions = fireworks.getExplosions(); - if (explosions.isEmpty()) { - return; + if (!explosions.isEmpty()) { + List explosionNbt = new ArrayList<>(); + for (Fireworks.FireworkExplosion explosion : explosions) { + explosionNbt.add(translateExplosionToBedrock(explosion)); + } + fireworksNbt.putList("Explosions", NbtType.COMPOUND, explosionNbt); + } else { + // This is the default firework + fireworksNbt.put("Explosions", NbtList.EMPTY); } - List explosionNbt = new ArrayList<>(); - for (Fireworks.FireworkExplosion explosion : explosions) { - explosionNbt.add(translateExplosionToBedrock(explosion)); - } - fireworksNbt.putList("Explosions", NbtType.COMPOUND, explosionNbt); builder.putCompound("Fireworks", fireworksNbt.build()); } @@ -138,4 +142,20 @@ public class FireworkRocketItem extends Item { return null; } } + + @Override + public void addRequiredNbt(GeyserSession session, @Nullable DataComponents components, BedrockItemBuilder builder) { + if (components != null) { + Fireworks fireworks = components.get(DataComponentType.FIREWORKS); + if (fireworks != null) { + // Already translated + return; + } + } + + NbtMapBuilder fireworksNbt = NbtMap.builder(); + fireworksNbt.putByte("Flight", (byte) 1); + fireworksNbt.put("Explosions", NbtList.EMPTY); + builder.putCompound("Fireworks", fireworksNbt.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 6a781dcb8..e9527872a 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 @@ -45,6 +45,7 @@ import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.components.Rarity; import org.geysermc.geyser.item.type.Item; +import org.geysermc.geyser.item.type.BedrockRequiresTagItem; import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; @@ -148,6 +149,12 @@ public final class ItemTranslator { if (components.get(DataComponentType.HIDE_TOOLTIP) != null) hideTooltips = true; } + // Fixes fireworks crafting recipe: they always contain a tag + // TODO remove once all items have their default components + if (javaItem instanceof BedrockRequiresTagItem requiresTagItem) { + requiresTagItem.addRequiredNbt(session, components, nbtBuilder); + } + Rarity rarity = javaItem.rarity(); boolean enchantmentGlint = javaItem.glint(); if (components != null) { 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 f9b840dd9..fd8981552 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,11 @@ package org.geysermc.geyser.translator.protocol.java; -import it.unimi.dsi.fastutil.ints.*; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.ints.IntIterator; +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; @@ -40,7 +44,11 @@ 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.*; +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.registry.Registries; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; @@ -58,7 +66,17 @@ import org.geysermc.mcprotocollib.protocol.data.game.recipe.data.SmithingTransfo 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.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; import java.util.stream.Collectors; import static org.geysermc.geyser.util.InventoryUtils.LAST_RECIPE_NET_ID; @@ -191,6 +209,9 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator { craftingDataPacket.getCraftingData().add(MultiRecipeData.of(UUID.fromString("85939755-ba10-4d9d-a4cc-efb7a8e943c4"), context.getAndIncrementNetId())); } + case CRAFTING_SPECIAL_FIREWORK_ROCKET -> { + craftingDataPacket.getCraftingData().add(MultiRecipeData.of(UUID.fromString("00000000-0000-0000-0000-000000000002"), context.getAndIncrementNetId())); + } default -> { List recipes = Registries.RECIPES.get(recipe.getType()); if (recipes != null) { @@ -427,7 +448,7 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator Date: Sat, 20 Jul 2024 23:21:36 -0400 Subject: [PATCH 167/233] Small cleanups --- README.md | 2 +- .../entity/type/living/animal/tameable/ParrotEntity.java | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/README.md b/README.md index 9469b1bb6..07f3df5aa 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ There are a few things Geyser is unable to support due to various differences be 3. Run `gradlew build` and locate to `bootstrap/build` folder. ## Contributing -Any contributions are appreciated. Please feel free to reach out to us on [Discord](http://discord.geysermc.org/) if +Any contributions are appreciated. Please feel free to reach out to us on [Discord](https://discord.gg/geysermc) if you're interested in helping out with Geyser. ## Libraries Used: 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 8baba6f00..69b19b1b9 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 @@ -31,7 +31,6 @@ 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; @@ -39,13 +38,9 @@ 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; public class ParrotEntity extends TameableEntity { - // Note: is the same as chicken. Reuse? - private static final Set TAMING_FOOD = Set.of(Items.WHEAT_SEEDS, Items.MELON_SEEDS, Items.PUMPKIN_SEEDS, Items.BEETROOT_SEEDS); - public ParrotEntity(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); } From 7d5c4a38f807c864c2784492b3aba0a7c79ef999 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sat, 20 Jul 2024 23:22:04 -0400 Subject: [PATCH 168/233] Respect block range attribute where we can #4864 --- .../entity/attribute/GeyserAttributeType.java | 1 + .../type/player/SessionPlayerEntity.java | 8 ++ ...BedrockInventoryTransactionTranslator.java | 81 +++++++++---------- 3 files changed, 49 insertions(+), 41 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 a4a0df8b8..3b543a943 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 @@ -50,6 +50,7 @@ public enum GeyserAttributeType { 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), + BLOCK_INTERACTION_RANGE("minecraft:player.block_interaction_range", null, 0.0f, 64f, 4.5f), // Bedrock Attributes ABSORPTION(null, "minecraft:absorption", 0f, 1024f, 0f), 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 45fea4d48..dc0545cee 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 @@ -64,6 +64,11 @@ public class SessionPlayerEntity extends PlayerEntity { */ @Getter protected final Map attributes = new Object2ObjectOpenHashMap<>(); + /** + * Java-only attribute + */ + @Getter + private double blockInteractionRange = GeyserAttributeType.BLOCK_INTERACTION_RANGE.getDefaultValue(); /** * Used in PlayerInputTranslator for movement checks. */ @@ -232,6 +237,8 @@ public class SessionPlayerEntity extends PlayerEntity { protected void updateAttribute(Attribute javaAttribute, List newAttributes) { if (javaAttribute.getType() == AttributeType.Builtin.GENERIC_ATTACK_SPEED) { session.setAttackSpeed(AttributeUtils.calculateValue(javaAttribute)); + } else if (javaAttribute.getType() == AttributeType.Builtin.PLAYER_BLOCK_INTERACTION_RANGE) { + this.blockInteractionRange = AttributeUtils.calculateValue(javaAttribute); } else { super.updateAttribute(javaAttribute, newAttributes); } @@ -295,6 +302,7 @@ public class SessionPlayerEntity extends PlayerEntity { public void resetAttributes() { attributes.clear(); maxHealth = GeyserAttributeType.MAX_HEALTH.getDefaultValue(); + blockInteractionRange = GeyserAttributeType.BLOCK_INTERACTION_RANGE.getDefaultValue(); UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket(); attributesPacket.setRuntimeEntityId(geyserId); 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 534a89e23..9d78d174b 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 @@ -70,7 +70,11 @@ 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.*; +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.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; @@ -78,7 +82,11 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.player.InteractActio 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 org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundInteractPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosRotPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundPlayerActionPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundSwingPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundUseItemOnPacket; import java.util.List; import java.util.concurrent.TimeUnit; @@ -90,11 +98,6 @@ import java.util.concurrent.TimeUnit; @Translator(packet = InventoryTransactionPacket.class) public class BedrockInventoryTransactionTranslator extends PacketTranslator { - private static final float MAXIMUM_BLOCK_PLACING_DISTANCE = 64f; - private static final int CREATIVE_EYE_HEIGHT_PLACE_DISTANCE = 49; - private static final int SURVIVAL_EYE_HEIGHT_PLACE_DISTANCE = 36; - private static final float MAXIMUM_BLOCK_DESTROYING_DISTANCE = 36f; - @Override public void translate(GeyserSession session, InventoryTransactionPacket packet) { if (packet.getTransactionType() == InventoryTransactionType.NORMAL && packet.getActions().size() == 3) { @@ -243,17 +246,13 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator - (creative ? CREATIVE_EYE_HEIGHT_PLACE_DISTANCE : SURVIVAL_EYE_HEIGHT_PLACE_DISTANCE)) { + if (!canInteractWithBlock(session, playerPosition, packetBlockPosition)) { restoreCorrectBlock(session, blockPos, packet); return; } @@ -262,26 +261,8 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator - (creative ? CREATIVE_EYE_HEIGHT_PLACE_DISTANCE : SURVIVAL_EYE_HEIGHT_PLACE_DISTANCE)) { - restoreCorrectBlock(session, blockPos, packet); - return; - } - Vector3f blockCenter = Vector3f.from(packetBlockPosition.getX() + 0.5f, packetBlockPosition.getY() + 0.5f, packetBlockPosition.getZ() + 0.5f); - // Vanilla check - if (!(session.getPlayerEntity().getPosition().sub(0, EntityDefinitions.PLAYER.offset(), 0) - .distanceSquared(blockCenter) < MAXIMUM_BLOCK_PLACING_DISTANCE)) { - // The client thinks that its blocks have been successfully placed. Restore the server's blocks instead. - restoreCorrectBlock(session, blockPos, packet); - return; - } - // More recent vanilla check (as of 1.18.2) double clickDistanceX = clickPositionFullX - blockCenter.getX(); double clickDistanceY = clickPositionFullY - blockCenter.getY(); double clickDistanceZ = clickPositionFullZ - blockCenter.getZ(); @@ -433,14 +414,10 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator MAXIMUM_BLOCK_DESTROYING_DISTANCE) { + playerPosition = playerPosition.down(EntityDefinitions.PLAYER.offset() - session.getEyeHeight()); + + if (!canInteractWithBlock(session, playerPosition, packet.getBlockPosition())) { restoreCorrectBlock(session, packet.getBlockPosition(), packet); return; } @@ -550,6 +527,28 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator(BlockPos) + float minX = packetBlockPosition.getX(); + float minY = packetBlockPosition.getY(); + float minZ = packetBlockPosition.getZ(); + float maxX = packetBlockPosition.getX() + 1; + float maxY = packetBlockPosition.getY() + 1; + float maxZ = packetBlockPosition.getZ() + 1; + + // AABB#distanceToSqr + float diffX = Math.max(Math.max(minX - playerPosition.getX(), playerPosition.getX() - maxX), 0); + float diffY = Math.max(Math.max(minY - playerPosition.getY(), playerPosition.getY() - maxY), 0); + float diffZ = Math.max(Math.max(minZ - playerPosition.getZ(), playerPosition.getZ() - maxZ), 0); + return ((diffX * diffX) + (diffY * diffY) + (diffZ * diffZ)) < (additionalRangeCheck * additionalRangeCheck); + } + /** * Restore the correct block state from the server without updating the chunk cache. * @@ -696,4 +695,4 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator Date: Sun, 21 Jul 2024 13:11:27 +0200 Subject: [PATCH 169/233] Fix: Text display offset (#4883) --- .../geysermc/geyser/entity/EntityDefinitions.java | 1 + .../geyser/entity/type/TextDisplayEntity.java | 12 +++++++++++- 2 files changed, 12 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 11b4a32d1..9063c7421 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -327,6 +327,7 @@ public final class EntityDefinitions { TEXT_DISPLAY = EntityDefinition.inherited(TextDisplayEntity::new, displayBase) .type(EntityType.TEXT_DISPLAY) .identifier("minecraft:armor_stand") + .offset(-0.5f) .addTranslator(MetadataType.CHAT, TextDisplayEntity::setText) .addTranslator(null) // Line width .addTranslator(null) // Background color 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 ff5604c19..8b47ce1ed 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 @@ -38,7 +38,17 @@ import java.util.UUID; // Note: 1.19.4 requires that the billboard is set to something in order to show, on Java Edition public class TextDisplayEntity extends DisplayBaseEntity { public TextDisplayEntity(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); + super(session, entityId, geyserId, uuid, definition, position.add(0, definition.offset(), 0), motion, yaw, pitch, headYaw); + } + + @Override + public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, boolean isOnGround) { + super.moveRelative(relX, relY + definition.offset(), relZ, yaw, pitch, isOnGround); + } + + @Override + public void moveAbsolute(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) { + super.moveAbsolute(position.add(Vector3f.from(0, definition.offset(), 0)), yaw, pitch, headYaw, isOnGround, teleported); } @Override From 1dd9ba3fb6e20a4df18580b9a4c45548ee2a3898 Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 22 Jul 2024 07:24:21 +0200 Subject: [PATCH 170/233] Fix: Allow items to be worn as hats if their Java base items also allow it (#4885) --- .../registry/populator/CustomItemRegistryPopulator.java | 8 +++++++- 1 file changed, 7 insertions(+), 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 a6fa164c1..0a9c93980 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 @@ -199,7 +199,13 @@ public class CustomItemRegistryPopulator { computeThrowableProperties(componentBuilder); } - computeRenderOffsets(false, customItemData, componentBuilder); + // Hardcoded on Java, and should extend to the custom item + boolean isHat = (javaItem.equals(Items.SKELETON_SKULL) || javaItem.equals(Items.WITHER_SKELETON_SKULL) + || javaItem.equals(Items.CARVED_PUMPKIN) || javaItem.equals(Items.ZOMBIE_HEAD) + || javaItem.equals(Items.PIGLIN_HEAD) || javaItem.equals(Items.DRAGON_HEAD) + || javaItem.equals(Items.CREEPER_HEAD) || javaItem.equals(Items.PLAYER_HEAD) + ); + computeRenderOffsets(isHat, customItemData, componentBuilder); componentBuilder.putCompound("item_properties", itemProperties.build()); builder.putCompound("components", componentBuilder.build()); From b113a6b185209bdc9718d81bed67c62a81375f2a Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 23 Jul 2024 15:43:57 -0400 Subject: [PATCH 171/233] Mark sequence position when block placing Fixes some instances between 1.19 and 1.20.5 when block ghosting could occur --- .../java/org/geysermc/geyser/session/cache/WorldCache.java | 2 +- .../bedrock/BedrockInventoryTransactionTranslator.java | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) 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 8eb715560..fb5137b05 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 @@ -201,4 +201,4 @@ public final class WorldCache { public String removeActiveRecord(Vector3i pos) { return this.activeRecords.remove(pos); } -} \ 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 9d78d174b..1e4c82da1 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 @@ -247,8 +247,6 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator Date: Tue, 23 Jul 2024 23:12:05 +0200 Subject: [PATCH 172/233] Fix: Sticky pistons not retracting on Geyser-Spigot/turning visually into normal pistons on all other platforms (#4891) --- .../java/level/JavaBlockEventTranslator.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) 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 f56750d12..ff861530a 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 @@ -43,7 +43,15 @@ import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator; import org.geysermc.geyser.translator.level.block.entity.PistonBlockEntity; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; -import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.*; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.BellValue; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.BlockValue; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.ChestValue; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.DecoratedPotValue; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.EndGatewayValue; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.MobSpawnerValue; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.NoteBlockValue; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValue; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType; import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundBlockEventPacket; @Translator(packet = ClientboundBlockEventPacket.class) @@ -80,7 +88,7 @@ public class JavaBlockEventTranslator extends PacketTranslator { BlockState state = session.getGeyser().getWorldManager().blockAt(session, position); - boolean sticky = state.is(Blocks.STICKY_PISTON); + boolean sticky = isSticky(state); boolean extended = action != PistonValueType.PUSHING; return new PistonBlockEntity(session, pos, direction, sticky, extended); }); @@ -149,4 +157,8 @@ public class JavaBlockEventTranslator extends PacketTranslator Date: Wed, 24 Jul 2024 14:27:05 -0400 Subject: [PATCH 173/233] Map unbreakable item component Fixes #4893 --- 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 57538565a..2417177ce 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 @@ -170,6 +170,11 @@ public class Item { builder.putInt("RepairCost", repairCost); } + // If the tag exists, it's unbreakable; the value is just weather to show the tooltip. As of Java 1.21 + if (components.getDataComponents().containsKey(DataComponentType.UNBREAKABLE)) { + builder.putByte("Unbreakable", (byte) 1); + } + // 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 From a85b312b40cb7f819d9cba896463ed3bfb38e4c5 Mon Sep 17 00:00:00 2001 From: Alex <40795980+AlexProgrammerDE@users.noreply.github.com> Date: Wed, 24 Jul 2024 23:06:59 +0200 Subject: [PATCH 174/233] Port to MinecraftAuth (#4779) Co-authored-by: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Co-authored-by: onebeastchris Co-authored-by: Camotoy <20743703+Camotoy@users.noreply.github.com> --- bootstrap/mod/fabric/build.gradle.kts | 2 +- core/build.gradle.kts | 5 +- .../java/org/geysermc/geyser/Constants.java | 4 +- .../java/org/geysermc/geyser/GeyserImpl.java | 91 +++++++-- .../geyser/item/type/PlayerHeadItem.java | 2 +- .../geyser/level/block/type/SkullBlock.java | 2 +- .../geyser/network/UpstreamPacketHandler.java | 6 +- .../geyser/session/GeyserSession.java | 192 +++++++++++------- .../PendingMicrosoftAuthentication.java | 136 +++++-------- .../geyser/skin/FakeHeadProvider.java | 16 +- .../translator/item/ItemTranslator.java | 14 +- ...SetLocalPlayerAsInitializedTranslator.java | 4 +- .../java/JavaGameProfileTranslator.java | 2 +- .../JavaPlayerInfoUpdateTranslator.java | 2 +- .../geyser/util/LoginEncryptionUtils.java | 6 +- .../geyser/util/MinecraftAuthLogger.java | 49 +++++ gradle/libs.versions.toml | 6 +- 17 files changed, 320 insertions(+), 219 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/util/MinecraftAuthLogger.java diff --git a/bootstrap/mod/fabric/build.gradle.kts b/bootstrap/mod/fabric/build.gradle.kts index 25bd0af9d..0d083fcf7 100644 --- a/bootstrap/mod/fabric/build.gradle.kts +++ b/bootstrap/mod/fabric/build.gradle.kts @@ -25,7 +25,7 @@ dependencies { 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.minecraftauth) { isTransitive = false } shadow(libs.raknet) { isTransitive = false } // Consequences of shading + relocating mcauthlib: shadow/relocate mcpl! diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 1d1794cf7..3b5cc3df9 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -25,11 +25,10 @@ dependencies { api(libs.bundles.protocol) - api(libs.mcauthlib) + api(libs.minecraftauth) api(libs.mcprotocollib) { exclude("io.netty", "netty-all") - exclude("com.github.GeyserMC", "packetlib") - exclude("com.github.GeyserMC", "mcauthlib") + exclude("net.raphimc", "MinecraftAuth") } implementation(libs.raknet) { diff --git a/core/src/main/java/org/geysermc/geyser/Constants.java b/core/src/main/java/org/geysermc/geyser/Constants.java index 588b25172..534cb30ad 100644 --- a/core/src/main/java/org/geysermc/geyser/Constants.java +++ b/core/src/main/java/org/geysermc/geyser/Constants.java @@ -39,7 +39,9 @@ public final class Constants { public static final String GEYSER_DOWNLOAD_LOCATION = "https://geysermc.org/download"; public static final String UPDATE_PERMISSION = "geyser.update"; + @Deprecated static final String SAVED_REFRESH_TOKEN_FILE = "saved-refresh-tokens.json"; + static final String SAVED_AUTH_CHAINS_FILE = "saved-auth-chains.json"; public static final String GEYSER_CUSTOM_NAMESPACE = "geyser_custom"; @@ -54,4 +56,4 @@ public final class Constants { } GLOBAL_API_WS_URI = wsUri; } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 9ee182edd..8f88f5b6a 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -29,6 +29,7 @@ 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.google.gson.Gson; import io.netty.channel.epoll.Epoll; import io.netty.util.NettyRuntime; import io.netty.util.concurrent.DefaultThreadFactory; @@ -38,6 +39,8 @@ import lombok.Getter; import lombok.Setter; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; +import net.raphimc.minecraftauth.step.java.session.StepFullJavaSession; +import net.raphimc.minecraftauth.step.msa.StepMsaToken; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -93,6 +96,7 @@ import org.geysermc.geyser.util.AssetUtils; import org.geysermc.geyser.util.CooldownUtils; import org.geysermc.geyser.util.DimensionUtils; import org.geysermc.geyser.util.Metrics; +import org.geysermc.geyser.util.MinecraftAuthLogger; import org.geysermc.geyser.util.NewsHandler; import org.geysermc.geyser.util.VersionCheckUtils; import org.geysermc.geyser.util.WebUtils; @@ -179,7 +183,7 @@ public class GeyserImpl implements GeyserApi { private PendingMicrosoftAuthentication pendingMicrosoftAuthentication; @Getter(AccessLevel.NONE) - private Map savedRefreshTokens; + private Map savedAuthChains; @Getter private static GeyserImpl instance; @@ -552,37 +556,84 @@ public class GeyserImpl implements GeyserApi { if (config.getRemote().authType() == AuthType.ONLINE) { // May be written/read to on multiple threads from each GeyserSession as well as writing the config - savedRefreshTokens = new ConcurrentHashMap<>(); + savedAuthChains = new ConcurrentHashMap<>(); - File tokensFile = bootstrap.getSavedUserLoginsFolder().resolve(Constants.SAVED_REFRESH_TOKEN_FILE).toFile(); - if (tokensFile.exists()) { + // TODO Remove after a while - just a migration help + //noinspection deprecation + File refreshTokensFile = bootstrap.getSavedUserLoginsFolder().resolve(Constants.SAVED_REFRESH_TOKEN_FILE).toFile(); + if (refreshTokensFile.exists()) { + logger.info("Migrating refresh tokens to auth chains..."); + TypeReference> type = new TypeReference<>() { }; + Map refreshTokens = null; + try { + refreshTokens = JSON_MAPPER.readValue(refreshTokensFile, type); + } catch (IOException e) { + // ignored - we'll just delete this file :)) + } + + if (refreshTokens != null) { + List validUsers = config.getSavedUserLogins(); + final Gson gson = new Gson(); + for (Map.Entry entry : refreshTokens.entrySet()) { + String user = entry.getKey(); + if (!validUsers.contains(user)) { + continue; + } + + // Migrate refresh tokens to auth chains + try { + StepFullJavaSession javaSession = PendingMicrosoftAuthentication.AUTH_FLOW.apply(false, 10); + StepFullJavaSession.FullJavaSession fullJavaSession = javaSession.getFromInput( + MinecraftAuthLogger.INSTANCE, + PendingMicrosoftAuthentication.AUTH_CLIENT, + new StepMsaToken.RefreshToken(entry.getValue()) + ); + + String authChain = gson.toJson(javaSession.toJson(fullJavaSession)); + savedAuthChains.put(user, authChain); + } catch (Exception e) { + GeyserImpl.getInstance().getLogger().warning("Could not migrate " + entry.getKey() + " to an auth chain! " + + "They will need to sign in the next time they join Geyser."); + } + + // Ensure the new additions are written to the file + scheduleAuthChainsWrite(); + } + } + + // Finally: Delete it. Goodbye! + refreshTokensFile.delete(); + } + + File authChainsFile = bootstrap.getSavedUserLoginsFolder().resolve(Constants.SAVED_AUTH_CHAINS_FILE).toFile(); + if (authChainsFile.exists()) { TypeReference> type = new TypeReference<>() { }; - Map refreshTokenFile = null; + Map authChainFile = null; try { - refreshTokenFile = JSON_MAPPER.readValue(tokensFile, type); + authChainFile = JSON_MAPPER.readValue(authChainsFile, type); } catch (IOException e) { logger.error("Cannot load saved user tokens!", e); } - if (refreshTokenFile != null) { + if (authChainFile != null) { List validUsers = config.getSavedUserLogins(); boolean doWrite = false; - for (Map.Entry entry : refreshTokenFile.entrySet()) { + for (Map.Entry entry : authChainFile.entrySet()) { String user = entry.getKey(); if (!validUsers.contains(user)) { // Perform a write to this file to purge the now-unused name doWrite = true; continue; } - savedRefreshTokens.put(user, entry.getValue()); + savedAuthChains.put(user, entry.getValue()); } if (doWrite) { - scheduleRefreshTokensWrite(); + scheduleAuthChainsWrite(); } } } } else { - savedRefreshTokens = null; + savedAuthChains = null; } newsHandler.handleNews(null, NewsItemAction.ON_SERVER_STARTED); @@ -829,11 +880,11 @@ public class GeyserImpl implements GeyserApi { } @Nullable - public String refreshTokenFor(@NonNull String bedrockName) { - return savedRefreshTokens.get(bedrockName); + public String authChainFor(@NonNull String bedrockName) { + return savedAuthChains.get(bedrockName); } - public void saveRefreshToken(@NonNull String bedrockName, @NonNull String refreshToken) { + public void saveAuthChain(@NonNull String bedrockName, @NonNull String authChain) { if (!getConfig().getSavedUserLogins().contains(bedrockName)) { // Do not save this login return; @@ -841,8 +892,8 @@ public class GeyserImpl implements GeyserApi { // We can safely overwrite old instances because MsaAuthenticationService#getLoginResponseFromRefreshToken // refreshes the token for us - if (!Objects.equals(refreshToken, savedRefreshTokens.put(bedrockName, refreshToken))) { - scheduleRefreshTokensWrite(); + if (!Objects.equals(authChain, savedAuthChains.put(bedrockName, authChain))) { + scheduleAuthChainsWrite(); } } @@ -852,15 +903,15 @@ public class GeyserImpl implements GeyserApi { } } - private void scheduleRefreshTokensWrite() { + private void scheduleAuthChainsWrite() { scheduledThread.execute(() -> { // Ensure all writes are handled on the same thread - File savedTokens = getBootstrap().getSavedUserLoginsFolder().resolve(Constants.SAVED_REFRESH_TOKEN_FILE).toFile(); + File savedAuthChains = getBootstrap().getSavedUserLoginsFolder().resolve(Constants.SAVED_AUTH_CHAINS_FILE).toFile(); TypeReference> type = new TypeReference<>() { }; - try (FileWriter writer = new FileWriter(savedTokens)) { + try (FileWriter writer = new FileWriter(savedAuthChains)) { JSON_MAPPER.writerFor(type) .withDefaultPrettyPrinter() - .writeValue(writer, savedRefreshTokens); + .writeValue(writer, this.savedAuthChains); } catch (IOException e) { getLogger().error("Unable to write saved refresh tokens!", e); } 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 86572d60c..d4999c80d 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.auth.data.GameProfile; +import org.geysermc.mcprotocollib.auth.GameProfile; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.session.GeyserSession; diff --git a/core/src/main/java/org/geysermc/geyser/level/block/type/SkullBlock.java b/core/src/main/java/org/geysermc/geyser/level/block/type/SkullBlock.java index c4aae46a2..6e791d674 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/type/SkullBlock.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/type/SkullBlock.java @@ -25,7 +25,7 @@ package org.geysermc.geyser.level.block.type; -import com.github.steveice10.mc.auth.data.GameProfile; +import org.geysermc.mcprotocollib.auth.GameProfile; 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/network/UpstreamPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java index c7aabb806..f56a8a43f 100644 --- a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java @@ -274,10 +274,10 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { private boolean couldLoginUserByName(String bedrockUsername) { if (geyser.getConfig().getSavedUserLogins().contains(bedrockUsername)) { - String refreshToken = geyser.refreshTokenFor(bedrockUsername); - if (refreshToken != null) { + String authChain = geyser.authChainFor(bedrockUsername); + if (authChain != null) { geyser.getLogger().info(GeyserLocale.getLocaleStringLog("geyser.auth.stored_credentials", session.getAuthData().name())); - session.authenticateWithRefreshToken(refreshToken); + session.authenticateWithAuthChain(authChain); return 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 c2f94b1c6..f7e3bd43d 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -25,9 +25,8 @@ 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.google.gson.Gson; +import com.google.gson.JsonObject; import io.netty.channel.Channel; import io.netty.channel.EventLoop; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; @@ -41,22 +40,60 @@ import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; import net.kyori.adventure.key.Key; +import net.raphimc.minecraftauth.step.java.StepMCProfile; +import net.raphimc.minecraftauth.step.java.StepMCToken; +import net.raphimc.minecraftauth.step.java.session.StepFullJavaSession; import org.checkerframework.checker.index.qual.NonNegative; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 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.*; +import org.cloudburstmc.math.vector.Vector2f; +import org.cloudburstmc.math.vector.Vector2i; +import org.cloudburstmc.math.vector.Vector3d; +import org.cloudburstmc.math.vector.Vector3f; +import org.cloudburstmc.math.vector.Vector3i; 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.Ability; +import org.cloudburstmc.protocol.bedrock.data.AbilityLayer; +import org.cloudburstmc.protocol.bedrock.data.AuthoritativeMovementMode; +import org.cloudburstmc.protocol.bedrock.data.ChatRestrictionLevel; +import org.cloudburstmc.protocol.bedrock.data.ExperimentData; +import org.cloudburstmc.protocol.bedrock.data.GamePublishSetting; +import org.cloudburstmc.protocol.bedrock.data.GameRuleData; +import org.cloudburstmc.protocol.bedrock.data.GameType; +import org.cloudburstmc.protocol.bedrock.data.PlayerPermission; +import org.cloudburstmc.protocol.bedrock.data.SoundEvent; +import org.cloudburstmc.protocol.bedrock.data.SpawnBiomeType; 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.bedrock.packet.AvailableEntityIdentifiersPacket; +import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket; +import org.cloudburstmc.protocol.bedrock.packet.BiomeDefinitionListPacket; +import org.cloudburstmc.protocol.bedrock.packet.CameraPresetsPacket; +import org.cloudburstmc.protocol.bedrock.packet.ChunkRadiusUpdatedPacket; +import org.cloudburstmc.protocol.bedrock.packet.CraftingDataPacket; +import org.cloudburstmc.protocol.bedrock.packet.CreativeContentPacket; +import org.cloudburstmc.protocol.bedrock.packet.EmoteListPacket; +import org.cloudburstmc.protocol.bedrock.packet.GameRulesChangedPacket; +import org.cloudburstmc.protocol.bedrock.packet.ItemComponentPacket; +import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEvent2Packet; +import org.cloudburstmc.protocol.bedrock.packet.PlayStatusPacket; +import org.cloudburstmc.protocol.bedrock.packet.SetTimePacket; +import org.cloudburstmc.protocol.bedrock.packet.StartGamePacket; +import org.cloudburstmc.protocol.bedrock.packet.SyncEntityPropertyPacket; +import org.cloudburstmc.protocol.bedrock.packet.TextPacket; +import org.cloudburstmc.protocol.bedrock.packet.TransferPacket; +import org.cloudburstmc.protocol.bedrock.packet.UpdateAbilitiesPacket; +import org.cloudburstmc.protocol.bedrock.packet.UpdateAdventureSettingsPacket; +import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; +import org.cloudburstmc.protocol.bedrock.packet.UpdateClientInputLocksPacket; +import org.cloudburstmc.protocol.bedrock.packet.UpdateSoftEnumPacket; import org.cloudburstmc.protocol.common.util.OptionalBoolean; import org.geysermc.api.util.BedrockPlatform; import org.geysermc.api.util.InputMode; @@ -106,7 +143,22 @@ import org.geysermc.geyser.registry.type.BlockMappings; import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.session.auth.AuthData; import org.geysermc.geyser.session.auth.BedrockClientData; -import org.geysermc.geyser.session.cache.*; +import org.geysermc.geyser.session.cache.AdvancementsCache; +import org.geysermc.geyser.session.cache.BookEditCache; +import org.geysermc.geyser.session.cache.ChunkCache; +import org.geysermc.geyser.session.cache.EntityCache; +import org.geysermc.geyser.session.cache.EntityEffectCache; +import org.geysermc.geyser.session.cache.FormCache; +import org.geysermc.geyser.session.cache.LodestoneCache; +import org.geysermc.geyser.session.cache.PistonCache; +import org.geysermc.geyser.session.cache.PreferencesCache; +import org.geysermc.geyser.session.cache.RegistryCache; +import org.geysermc.geyser.session.cache.SkullCache; +import org.geysermc.geyser.session.cache.StructureBlockCache; +import org.geysermc.geyser.session.cache.TagCache; +import org.geysermc.geyser.session.cache.TeleportCache; +import org.geysermc.geyser.session.cache.WorldBorder; +import org.geysermc.geyser.session.cache.WorldCache; import org.geysermc.geyser.skin.FloodgateSkinUploader; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.text.MinecraftLocale; @@ -116,9 +168,15 @@ 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.geysermc.geyser.util.MinecraftAuthLogger; +import org.geysermc.mcprotocollib.auth.GameProfile; import org.geysermc.mcprotocollib.network.BuiltinFlags; import org.geysermc.mcprotocollib.network.Session; -import org.geysermc.mcprotocollib.network.event.session.*; +import org.geysermc.mcprotocollib.network.event.session.ConnectedEvent; +import org.geysermc.mcprotocollib.network.event.session.DisconnectedEvent; +import org.geysermc.mcprotocollib.network.event.session.PacketErrorEvent; +import org.geysermc.mcprotocollib.network.event.session.PacketSendingEvent; +import org.geysermc.mcprotocollib.network.event.session.SessionAdapter; import org.geysermc.mcprotocollib.network.packet.Packet; import org.geysermc.mcprotocollib.network.tcp.TcpClientSession; import org.geysermc.mcprotocollib.network.tcp.TcpSession; @@ -153,7 +211,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; @@ -163,6 +230,8 @@ import java.util.concurrent.atomic.AtomicInteger; @Getter public class GeyserSession implements GeyserConnection, GeyserCommandSource { + private static final Gson GSON = new Gson(); + private final GeyserImpl geyser; private final UpstreamSession upstream; private DownstreamSession downstream; @@ -690,7 +759,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { } } - public void authenticateWithRefreshToken(String refreshToken) { + public void authenticateWithAuthChain(String authChain) { if (loggedIn) { geyser.getLogger().severe(GeyserLocale.getLocaleStringLog("geyser.auth.already_loggedin", getAuthData().name())); return; @@ -699,24 +768,23 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { loggingIn = true; CompletableFuture.supplyAsync(() -> { - MsaAuthenticationService service = new MsaAuthenticationService(GeyserImpl.OAUTH_CLIENT_ID); - service.setRefreshToken(refreshToken); + StepFullJavaSession step = PendingMicrosoftAuthentication.AUTH_FLOW.apply(true, 30); + StepFullJavaSession.FullJavaSession response; try { - service.login(); - } catch (RequestException e) { - geyser.getLogger().error("Error while attempting to use refresh token for " + bedrockUsername() + "!", e); + response = step.refresh(MinecraftAuthLogger.INSTANCE, PendingMicrosoftAuthentication.AUTH_CLIENT, step.fromJson(GSON.fromJson(authChain, JsonObject.class))); + } catch (Exception e) { + geyser.getLogger().error("Error while attempting to use auth chain for " + bedrockUsername() + "!", e); return Boolean.FALSE; } - GameProfile profile = service.getSelectedProfile(); - if (profile == null) { - // Java account is offline - disconnect(GeyserLocale.getPlayerLocaleString("geyser.network.remote.invalid_account", clientData.getLanguageCode())); - return null; - } + StepMCProfile.MCProfile mcProfile = response.getMcProfile(); + StepMCToken.MCToken mcToken = mcProfile.getMcToken(); - protocol = new MinecraftProtocol(profile, service.getAccessToken()); - geyser.saveRefreshToken(bedrockUsername(), service.getRefreshToken()); + protocol = new MinecraftProtocol( + new GameProfile(mcProfile.getId(), mcProfile.getName()), + mcToken.getAccessToken() + ); + geyser.saveAuthChain(bedrockUsername(), GSON.toJson(step.toJson(response))); return Boolean.TRUE; }).whenComplete((successful, ex) -> { if (this.closed) { @@ -761,25 +829,15 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { final PendingMicrosoftAuthentication.AuthenticationTask task = geyser.getPendingMicrosoftAuthentication().getOrCreateTask( getAuthData().xuid() ); - task.setOnline(true); - task.resetTimer(); - - if (task.getAuthentication().isDone()) { + if (task.getAuthentication() != null && task.getAuthentication().isDone()) { onMicrosoftLoginComplete(task); } else { - task.getCode(offlineAccess).whenComplete((response, ex) -> { - boolean connected = !closed; - if (ex != null) { - if (connected) { - geyser.getLogger().error("Failed to get Microsoft auth code", ex); - disconnect(ex.toString()); - } - task.cleanup(); // error getting auth code -> clean up immediately - } else if (connected) { - LoginEncryptionUtils.buildAndShowMicrosoftCodeWindow(this, response); - task.getAuthentication().whenComplete((r, $) -> onMicrosoftLoginComplete(task)); + task.resetRunningFlow(); + task.performLoginAttempt(offlineAccess, code -> { + if (!closed) { + LoginEncryptionUtils.buildAndShowMicrosoftCodeWindow(this, code); } - }); + }).handle((r, e) -> onMicrosoftLoginComplete(task)); } } @@ -791,36 +849,32 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { return false; } task.cleanup(); // player is online -> remove pending authentication immediately - Throwable ex = task.getLoginException(); - if (ex != null) { - geyser.getLogger().error("Failed to log in with Microsoft code!", ex); - disconnect(ex.toString()); - } else { - MsaAuthenticationService service = task.getMsaAuthenticationService(); - GameProfile selectedProfile = service.getSelectedProfile(); - if (selectedProfile == null) { - disconnect(GeyserLocale.getPlayerLocaleString( - "geyser.network.remote.invalid_account", - clientData.getLanguageCode() - )); - } else { - this.protocol = new MinecraftProtocol( - selectedProfile, - service.getAccessToken() - ); - try { - connectDownstream(); - } catch (Throwable t) { - t.printStackTrace(); - return false; - } + return task.getAuthentication().handle((result, ex) -> { + if (ex != null) { + geyser.getLogger().error("Failed to log in with Microsoft code!", ex); + disconnect(ex.toString()); + return false; + } - // Save our refresh token for later use - geyser.saveRefreshToken(bedrockUsername(), service.getRefreshToken()); - return true; - } - } - return false; + StepMCProfile.MCProfile mcProfile = result.session().getMcProfile(); + StepMCToken.MCToken mcToken = mcProfile.getMcToken(); + + this.protocol = new MinecraftProtocol( + new GameProfile(mcProfile.getId(), mcProfile.getName()), + mcToken.getAccessToken() + ); + + try { + connectDownstream(); + } catch (Throwable t) { + t.printStackTrace(); + return false; + } + + // Save our auth chain for later use + geyser.saveAuthChain(bedrockUsername(), GSON.toJson(result.step().toJson(result.session()))); + return true; + }).getNow(false); } /** @@ -1103,7 +1157,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { if (authData != null) { PendingMicrosoftAuthentication.AuthenticationTask task = geyser.getPendingMicrosoftAuthentication().getTask(authData.xuid()); if (task != null) { - task.setOnline(false); + task.resetRunningFlow(); } } } 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 0651039a0..7d0e2fbf9 100644 --- a/core/src/main/java/org/geysermc/geyser/session/PendingMicrosoftAuthentication.java +++ b/core/src/main/java/org/geysermc/geyser/session/PendingMicrosoftAuthentication.java @@ -25,27 +25,44 @@ package org.geysermc.geyser.session; -import com.github.steveice10.mc.auth.exception.request.AuthPendingException; -import com.github.steveice10.mc.auth.exception.request.RequestException; -import com.github.steveice10.mc.auth.service.MsaAuthenticationService; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import lombok.Getter; import lombok.Setter; import lombok.SneakyThrows; +import net.lenni0451.commons.httpclient.HttpClient; +import net.raphimc.minecraftauth.MinecraftAuth; +import net.raphimc.minecraftauth.step.java.session.StepFullJavaSession; +import net.raphimc.minecraftauth.step.msa.StepMsaDeviceCode; +import net.raphimc.minecraftauth.util.MicrosoftConstants; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserLogger; +import org.geysermc.geyser.util.MinecraftAuthLogger; -import java.io.Serial; -import java.util.concurrent.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; +import java.util.function.BiFunction; +import java.util.function.Consumer; /** * Pending Microsoft authentication task cache. * It permits user to exit the server while they authorize Geyser to access their Microsoft account. */ public class PendingMicrosoftAuthentication { + public static final HttpClient AUTH_CLIENT = MinecraftAuth.createHttpClient(); + public static final BiFunction AUTH_FLOW = (offlineAccess, timeoutSec) -> MinecraftAuth.builder() + .withClientId(GeyserImpl.OAUTH_CLIENT_ID) + .withScope(offlineAccess ? "XboxLive.signin XboxLive.offline_access" : "XboxLive.signin") + .withTimeout(timeoutSec) + .deviceCode() + .withoutDeviceToken() + .regularAuthentication(MicrosoftConstants.JAVA_XSTS_RELYING_PARTY) + .buildMinecraftJavaProfileStep(false); /** * For GeyserConnect usage. */ @@ -57,8 +74,8 @@ public class PendingMicrosoftAuthentication { .build(new CacheLoader<>() { @Override public AuthenticationTask load(@NonNull String userKey) { - return storeServerInformation ? new ProxyAuthenticationTask(userKey, timeoutSeconds * 1000L) - : new AuthenticationTask(userKey, timeoutSeconds * 1000L); + return storeServerInformation ? new ProxyAuthenticationTask(userKey, timeoutSeconds) + : new AuthenticationTask(userKey, timeoutSeconds); } }); } @@ -80,37 +97,23 @@ public class PendingMicrosoftAuthentication { public class AuthenticationTask { private static final Executor DELAYED_BY_ONE_SECOND = CompletableFuture.delayedExecutor(1, TimeUnit.SECONDS); - @Getter - private final MsaAuthenticationService msaAuthenticationService = new MsaAuthenticationService(GeyserImpl.OAUTH_CLIENT_ID); private final String userKey; - private final long timeoutMs; - - private long remainingTimeMs; - - @Setter - private boolean online = true; - + private final int timeoutSec; @Getter - private final CompletableFuture authentication; + private CompletableFuture authentication; - @Getter - private volatile Throwable loginException; - - private AuthenticationTask(String userKey, long timeoutMs) { + private AuthenticationTask(String userKey, int timeoutSec) { this.userKey = userKey; - this.timeoutMs = timeoutMs; - this.remainingTimeMs = timeoutMs; - - this.authentication = new CompletableFuture<>(); - this.authentication.whenComplete((r, ex) -> { - this.loginException = ex; - // avoid memory leak, in case player doesn't connect again - CompletableFuture.delayedExecutor(timeoutMs, TimeUnit.MILLISECONDS).execute(this::cleanup); - }); + this.timeoutSec = timeoutSec; } - public void resetTimer() { - this.remainingTimeMs = this.timeoutMs; + public void resetRunningFlow() { + if (authentication == null) { + return; + } + + // Interrupt the current flow + this.authentication.cancel(true); } public void cleanup() { @@ -121,52 +124,18 @@ public class PendingMicrosoftAuthentication { authentications.invalidate(userKey); } - public CompletableFuture getCode(boolean offlineAccess) { - // Request the code - 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; - } - - /** - * @param offlineAccess whether we want a refresh token for later use. - */ - private MsaAuthenticationService.MsCodeResponse tryGetCode(boolean offlineAccess) throws CompletionException { - try { - return msaAuthenticationService.getAuthCode(offlineAccess); - } catch (RequestException e) { - throw new CompletionException(e); - } - } - - private void performLoginAttempt(long lastAttempt) { - CompletableFuture.runAsync(() -> { + public CompletableFuture performLoginAttempt(boolean offlineAccess, Consumer deviceCodeConsumer) { + return authentication = CompletableFuture.supplyAsync(() -> { try { - msaAuthenticationService.login(); - } catch (AuthPendingException e) { - long currentAttempt = System.currentTimeMillis(); - if (!online) { - // decrement timer only when player's offline - remainingTimeMs -= currentAttempt - lastAttempt; - if (remainingTimeMs <= 0L) { - // time's up - authentication.completeExceptionally(new TaskTimeoutException()); - cleanup(); - return; - } - } - // try again in 1 second - performLoginAttempt(currentAttempt); - return; + StepFullJavaSession step = AUTH_FLOW.apply(offlineAccess, timeoutSec); + return new StepChainResult(step, step.getFromInput(MinecraftAuthLogger.INSTANCE, AUTH_CLIENT, new StepMsaDeviceCode.MsaDeviceCodeCallback(deviceCodeConsumer))); } catch (Exception e) { - authentication.completeExceptionally(e); - return; + throw new CompletionException(e); } - // login successful - authentication.complete(msaAuthenticationService); - }, DELAYED_BY_ONE_SECOND); + }, DELAYED_BY_ONE_SECOND).whenComplete((r, ex) -> { + // avoid memory leak, in case player doesn't connect again + CompletableFuture.delayedExecutor(timeoutSec, TimeUnit.SECONDS).execute(this::cleanup); + }); } @Override @@ -181,22 +150,11 @@ public class PendingMicrosoftAuthentication { private String server; private int port; - private ProxyAuthenticationTask(String userKey, long timeoutMs) { - super(userKey, timeoutMs); + private ProxyAuthenticationTask(String userKey, int timeoutSec) { + super(userKey, timeoutSec); } } - /** - * @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."); - } + public record StepChainResult(StepFullJavaSession step, StepFullJavaSession.FullJavaSession session) { } } 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 ef3ff3293..6f6bcb0ae 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/FakeHeadProvider.java +++ b/core/src/main/java/org/geysermc/geyser/skin/FakeHeadProvider.java @@ -25,11 +25,10 @@ package org.geysermc.geyser.skin; -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 org.geysermc.mcprotocollib.auth.GameProfile; +import org.geysermc.mcprotocollib.auth.GameProfile.Texture; +import org.geysermc.mcprotocollib.auth.GameProfile.TextureModel; +import org.geysermc.mcprotocollib.auth.GameProfile.TextureType; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; @@ -113,12 +112,7 @@ public class FakeHeadProvider { return; } - Map textures = null; - try { - textures = profile.getTextures(false); - } catch (PropertyException e) { - session.getGeyser().getLogger().debug("Failed to get textures from GameProfile: " + e); - } + Map textures = profile.getTextures(false); if (textures == null || textures.isEmpty()) { loadHead(session, entity, profile.getName()); 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 e9527872a..aa0c3eb43 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,10 +25,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 org.geysermc.mcprotocollib.auth.GameProfile; +import org.geysermc.mcprotocollib.auth.GameProfile.Texture; +import org.geysermc.mcprotocollib.auth.GameProfile.TextureType; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.checkerframework.checker.nullness.qual.NonNull; @@ -487,12 +486,7 @@ public final class ItemTranslator { GameProfile profile = components.get(DataComponentType.PROFILE); if (profile != null) { - Map textures = null; - try { - textures = profile.getTextures(false); - } catch (PropertyException e) { - GeyserImpl.getInstance().getLogger().debug("Failed to get textures from GameProfile: " + e); - } + Map textures = profile.getTextures(false); if (textures == null || textures.isEmpty()) { return null; 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 de2df0cb7..47c5bfd35 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 @@ -46,10 +46,10 @@ public class BedrockSetLocalPlayerAsInitializedTranslator extends PacketTranslat if (session.remoteServer().authType() == AuthType.ONLINE) { if (!session.isLoggedIn()) { if (session.getGeyser().getConfig().getSavedUserLogins().contains(session.bedrockUsername())) { - if (session.getGeyser().refreshTokenFor(session.bedrockUsername()) == null) { + if (session.getGeyser().authChainFor(session.bedrockUsername()) == null) { LoginEncryptionUtils.buildAndShowConsentWindow(session); } else { - // If the refresh token is not null and we're here, then the refresh token expired + // If the auth chain is not null and we're here, then it expired // and the expiration form has been cached session.getFormCache().resendAllForms(); } 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 e7bde6a9d..47d1cff08 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 @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java; -import com.github.steveice10.mc.auth.data.GameProfile; +import org.geysermc.mcprotocollib.auth.GameProfile; import net.kyori.adventure.key.Key; import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.entity.type.player.PlayerEntity; 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 f5ea4c08d..19f34db74 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 @@ -25,7 +25,7 @@ package org.geysermc.geyser.translator.protocol.java.entity.player; -import com.github.steveice10.mc.auth.data.GameProfile; +import org.geysermc.mcprotocollib.auth.GameProfile; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.packet.PlayerListPacket; 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 478a6ef96..d3024be65 100644 --- a/core/src/main/java/org/geysermc/geyser/util/LoginEncryptionUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/LoginEncryptionUtils.java @@ -28,7 +28,7 @@ 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.github.steveice10.mc.auth.service.MsaAuthenticationService; +import net.raphimc.minecraftauth.step.msa.StepMsaDeviceCode; import org.cloudburstmc.protocol.bedrock.packet.LoginPacket; import org.cloudburstmc.protocol.bedrock.packet.ServerToClientHandshakePacket; import org.cloudburstmc.protocol.bedrock.util.ChainValidationResult; @@ -203,7 +203,7 @@ public class LoginEncryptionUtils { /** * Shows the code that a user must input into their browser */ - public static void buildAndShowMicrosoftCodeWindow(GeyserSession session, MsaAuthenticationService.MsCodeResponse msCode) { + public static void buildAndShowMicrosoftCodeWindow(GeyserSession session, StepMsaDeviceCode.MsaDeviceCode msCode) { String locale = session.locale(); StringBuilder message = new StringBuilder("%xbox.signin.website\n") @@ -212,7 +212,7 @@ public class LoginEncryptionUtils { .append(ChatColor.RESET) .append("\n%xbox.signin.enterCode\n") .append(ChatColor.GREEN) - .append(msCode.user_code); + .append(msCode.getUserCode()); int timeout = session.getGeyser().getConfig().getPendingAuthenticationTimeout(); if (timeout != 0) { message.append("\n\n") diff --git a/core/src/main/java/org/geysermc/geyser/util/MinecraftAuthLogger.java b/core/src/main/java/org/geysermc/geyser/util/MinecraftAuthLogger.java new file mode 100644 index 000000000..4e928d47e --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/util/MinecraftAuthLogger.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 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 net.raphimc.minecraftauth.util.logging.ILogger; +import org.geysermc.geyser.GeyserImpl; + +public class MinecraftAuthLogger implements ILogger { + + public static final MinecraftAuthLogger INSTANCE = new MinecraftAuthLogger(); + + @Override + public void info(String message) { + GeyserImpl.getInstance().getLogger().debug(message); + } + + @Override + public void warn(String message) { + GeyserImpl.getInstance().getLogger().warning(message); + } + + @Override + public void error(String message) { + GeyserImpl.getInstance().getLogger().error(message); + } +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 49c02d190..845589585 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,8 +12,8 @@ gson = "2.3.1" # Provided by Spigot 1.8.8 websocket = "1.5.1" protocol = "3.0.0.Beta2-20240704.153116-14" raknet = "1.0.0.CR3-20240416.144209-1" -mcauthlib = "e5b0bcc" -mcprotocollib = "1.21-20240616.154144-5" +minecraftauth = "4.1.0" +mcprotocollib = "1.21-20240718.102029-13" adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" @@ -107,7 +107,7 @@ commodore = { group = "me.lucko", name = "commodore", version.ref = "commodore" 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" } +minecraftauth = { group = "net.raphimc", name = "MinecraftAuth", version.ref = "minecraftauth" } mcprotocollib = { group = "org.geysermc.mcprotocollib", name = "protocol", version.ref = "mcprotocollib" } raknet = { group = "org.cloudburstmc.netty", name = "netty-transport-raknet", version.ref = "raknet" } terminalconsoleappender = { group = "net.minecrell", name = "terminalconsoleappender", version.ref = "terminalconsoleappender" } From 5ebb16a1920e75dd91dec8217ef3f06a1d2a2355 Mon Sep 17 00:00:00 2001 From: Eclipse Date: Thu, 25 Jul 2024 10:38:12 +0000 Subject: [PATCH 175/233] Update MCPL (#4897) --- 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 845589585..58b5310ac 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ websocket = "1.5.1" protocol = "3.0.0.Beta2-20240704.153116-14" raknet = "1.0.0.CR3-20240416.144209-1" minecraftauth = "4.1.0" -mcprotocollib = "1.21-20240718.102029-13" +mcprotocollib = "1.21-20240725.013034-16" adventure = "4.14.0" adventure-platform = "4.3.0" junit = "5.9.2" From e994d6e1d6929750d63a81c57d0f0d8f3497673d Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Fri, 26 Jul 2024 16:51:22 -0400 Subject: [PATCH 176/233] Bring in #4847 change --- .../org/geysermc/geyser/util/DimensionUtils.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) 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 cd1a690c3..b1408b817 100644 --- a/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java @@ -27,9 +27,11 @@ package org.geysermc.geyser.util; 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.packet.ChangeDimensionPacket; import org.cloudburstmc.protocol.bedrock.packet.ChunkRadiusUpdatedPacket; +import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; import org.cloudburstmc.protocol.bedrock.packet.MobEffectPacket; import org.cloudburstmc.protocol.bedrock.packet.PlayerActionPacket; import org.cloudburstmc.protocol.bedrock.packet.StopSoundPacket; @@ -85,6 +87,20 @@ public class DimensionUtils { // Effects are re-sent from server entityEffects.clear(); + // Always reset weather, as it sometimes suddenly starts raining. See https://github.com/GeyserMC/Geyser/issues/3679 + LevelEventPacket stopRainPacket = new LevelEventPacket(); + stopRainPacket.setType(LevelEvent.STOP_RAINING); + stopRainPacket.setData(0); + stopRainPacket.setPosition(Vector3f.ZERO); + session.sendUpstreamPacket(stopRainPacket); + session.setRaining(false); + LevelEventPacket stopThunderPacket = new LevelEventPacket(); + stopThunderPacket.setType(LevelEvent.STOP_THUNDERSTORM); + stopThunderPacket.setData(0); + stopThunderPacket.setPosition(Vector3f.ZERO); + session.sendUpstreamPacket(stopThunderPacket); + session.setThunder(false); + finalizeDimensionSwitch(session, player); // If the bedrock nether height workaround is enabled, meaning the client is told it's in the end dimension, From 663e3af7c8f10e5ae9e4fc5d76ad32b8730b26c9 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Fri, 26 Jul 2024 17:22:10 -0400 Subject: [PATCH 177/233] Fix non-block items in stonecutters Fixes #4845 --- .../geysermc/geyser/item/type/BlockItem.java | 13 ++++++++++++ .../org/geysermc/geyser/item/type/Item.java | 11 +++++++--- .../java/JavaUpdateRecipesTranslator.java | 3 ++- .../geysermc/geyser/util/StatisticsUtils.java | 20 +++++++------------ 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/item/type/BlockItem.java b/core/src/main/java/org/geysermc/geyser/item/type/BlockItem.java index 30a31a100..c57e58469 100644 --- a/core/src/main/java/org/geysermc/geyser/item/type/BlockItem.java +++ b/core/src/main/java/org/geysermc/geyser/item/type/BlockItem.java @@ -28,6 +28,9 @@ package org.geysermc.geyser.item.type; import org.geysermc.geyser.level.block.type.Block; public class BlockItem extends Item { + // If item is instanceof ItemNameBlockItem + private final boolean treatLikeBlock; + public BlockItem(Builder builder, Block block, Block... otherBlocks) { super(block.javaIdentifier().value(), builder); @@ -36,6 +39,7 @@ public class BlockItem extends Item { for (Block otherBlock : otherBlocks) { registerBlock(otherBlock, this); } + treatLikeBlock = true; } // Use this constructor if the item name is not the same as its primary block @@ -46,5 +50,14 @@ public class BlockItem extends Item { for (Block otherBlock : otherBlocks) { registerBlock(otherBlock, this); } + treatLikeBlock = false; + } + + @Override + public String translationKey() { + if (!treatLikeBlock) { + return super.translationKey(); + } + return "block." + this.javaIdentifier.namespace() + "." + this.javaIdentifier.value(); } } 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 2417177ce..a8a477025 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,6 +25,7 @@ package org.geysermc.geyser.item.type; +import net.kyori.adventure.key.Key; import net.kyori.adventure.text.Component; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -59,7 +60,7 @@ import java.util.Map; public class Item { private static final Map BLOCK_TO_ITEM = new HashMap<>(); - private final String javaIdentifier; + protected final Key javaIdentifier; private int javaId = -1; private final int stackSize; private final int attackDamage; @@ -68,7 +69,7 @@ public class Item { private final boolean glint; public Item(String javaIdentifier, Builder builder) { - this.javaIdentifier = MinecraftKey.key(javaIdentifier).asString().intern(); + this.javaIdentifier = MinecraftKey.key(javaIdentifier); this.stackSize = builder.stackSize; this.maxDamage = builder.maxDamage; this.attackDamage = builder.attackDamage; @@ -77,7 +78,7 @@ public class Item { } public String javaIdentifier() { - return javaIdentifier; + return javaIdentifier.asString(); } public int javaId() { @@ -108,6 +109,10 @@ public class Item { return false; } + public String translationKey() { + return "item." + javaIdentifier.namespace() + "." + javaIdentifier.value(); + } + /* Translation methods to Bedrock and back */ public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) { 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 fd8981552..7c36c505b 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 @@ -253,7 +253,8 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator Registries.JAVA_ITEMS.get().get(stoneCuttingRecipeData.getResult().getId()) - .javaIdentifier()))); + // See RecipeManager#getRecipesFor as of 1.21 + .translationKey()))); // Now that it's sorted, let's translate these recipes int buttonId = 0; 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 72fcb4fa6..9847c0cfc 100644 --- a/core/src/main/java/org/geysermc/geyser/util/StatisticsUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/StatisticsUtils.java @@ -107,7 +107,7 @@ public class StatisticsUtils { for (Object2IntMap.Entry entry : session.getStatistics().object2IntEntrySet()) { if (entry.getKey() instanceof BreakItemStatistic statistic) { - String item = itemRegistry.get(statistic.getId()).javaIdentifier(); + Item item = itemRegistry.get(statistic.getId()); content.add(getItemTranslateKey(item, language) + ": " + entry.getIntValue()); } } @@ -117,7 +117,7 @@ public class StatisticsUtils { for (Object2IntMap.Entry entry : session.getStatistics().object2IntEntrySet()) { if (entry.getKey() instanceof CraftItemStatistic statistic) { - String item = itemRegistry.get(statistic.getId()).javaIdentifier(); + Item item = itemRegistry.get(statistic.getId()); content.add(getItemTranslateKey(item, language) + ": " + entry.getIntValue()); } } @@ -127,7 +127,7 @@ public class StatisticsUtils { for (Object2IntMap.Entry entry : session.getStatistics().object2IntEntrySet()) { if (entry.getKey() instanceof UseItemStatistic statistic) { - String item = itemRegistry.get(statistic.getId()).javaIdentifier(); + Item item = itemRegistry.get(statistic.getId()); content.add(getItemTranslateKey(item, language) + ": " + entry.getIntValue()); } } @@ -137,7 +137,7 @@ public class StatisticsUtils { for (Object2IntMap.Entry entry : session.getStatistics().object2IntEntrySet()) { if (entry.getKey() instanceof PickupItemStatistic statistic) { - String item = itemRegistry.get(statistic.getId()).javaIdentifier(); + Item item = itemRegistry.get(statistic.getId()); content.add(getItemTranslateKey(item, language) + ": " + entry.getIntValue()); } } @@ -147,7 +147,7 @@ public class StatisticsUtils { for (Object2IntMap.Entry entry : session.getStatistics().object2IntEntrySet()) { if (entry.getKey() instanceof DropItemStatistic statistic) { - String item = itemRegistry.get(statistic.getId()).javaIdentifier(); + Item item = itemRegistry.get(statistic.getId()); content.add(getItemTranslateKey(item, language) + ": " + entry.getIntValue()); } } @@ -208,14 +208,8 @@ public class StatisticsUtils { * @param language the language to search in * @return the full name of the item */ - private static String getItemTranslateKey(String item, String language) { - item = item.replace("minecraft:", "item.minecraft."); - String translatedItem = MinecraftLocale.getLocaleString(item, language); - if (translatedItem.equals(item)) { - // Didn't translate; must be a block - translatedItem = MinecraftLocale.getLocaleString(item.replace("item.", "block."), language); - } - return translatedItem; + private static String getItemTranslateKey(Item item, String language) { + return MinecraftLocale.getLocaleString(item.translationKey(), language); } private static String translate(String keys, String locale) { From 258d6aadb436c29b0ea969c52564b571983c9c02 Mon Sep 17 00:00:00 2001 From: chris Date: Sat, 27 Jul 2024 00:39:45 +0200 Subject: [PATCH 178/233] Fix: Bedrock players being able to always eat food while in peaceful difficulty (#4904) --- .../BedrockServerSettingsRequestTranslator.java | 10 ++++++++++ .../java/JavaChangeDifficultyTranslator.java | 14 +++++++++++--- .../org/geysermc/geyser/util/SettingsUtils.java | 15 +++++++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) 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 aa7a2e40f..c7475e5d0 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 @@ -27,12 +27,14 @@ package org.geysermc.geyser.translator.protocol.bedrock; import org.cloudburstmc.protocol.bedrock.packet.ServerSettingsRequestPacket; import org.cloudburstmc.protocol.bedrock.packet.ServerSettingsResponsePacket; +import org.cloudburstmc.protocol.bedrock.packet.SetDifficultyPacket; import org.geysermc.cumulus.form.CustomForm; import org.geysermc.cumulus.form.impl.FormDefinitions; 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.SettingsUtils; +import org.geysermc.mcprotocollib.protocol.data.game.setting.Difficulty; import java.util.concurrent.TimeUnit; @@ -47,6 +49,14 @@ public class BedrockServerSettingsRequestTranslator extends PacketTranslator { @Override public void translate(GeyserSession session, ClientboundChangeDifficultyPacket packet) { + Difficulty difficulty = packet.getDifficulty(); + session.getWorldCache().setDifficulty(difficulty); + + // Peaceful difficulty allows always eating food - hence, we just do not send it to Bedrock. + if (difficulty == Difficulty.PEACEFUL) { + difficulty = Difficulty.EASY; + } + SetDifficultyPacket setDifficultyPacket = new SetDifficultyPacket(); - setDifficultyPacket.setDifficulty(packet.getDifficulty().ordinal()); + setDifficultyPacket.setDifficulty(difficulty.ordinal()); session.sendUpstreamPacket(setDifficultyPacket); - session.getWorldCache().setDifficulty(packet.getDifficulty()); } } 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 ed97408b9..6f46b191c 100644 --- a/core/src/main/java/org/geysermc/geyser/util/SettingsUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/SettingsUtils.java @@ -25,6 +25,7 @@ package org.geysermc.geyser.util; +import org.cloudburstmc.protocol.bedrock.packet.SetDifficultyPacket; import org.geysermc.cumulus.component.DropdownComponent; import org.geysermc.cumulus.form.CustomForm; import org.geysermc.geyser.GeyserImpl; @@ -33,6 +34,7 @@ import org.geysermc.geyser.level.WorldManager; 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.setting.Difficulty; public class SettingsUtils { /** @@ -96,6 +98,7 @@ public class SettingsUtils { } builder.validResultHandler((response) -> { + applyDifficultyFix(session); if (showClientSettings) { // Client can only see its coordinates if reducedDebugInfo is disabled and coordinates are enabled in geyser config. if (showCoordinates) { @@ -134,9 +137,21 @@ public class SettingsUtils { } }); + builder.closedOrInvalidResultHandler($ -> applyDifficultyFix(session)); + return builder.build(); } + private static void applyDifficultyFix(GeyserSession session) { + // Peaceful difficulty allows always eating food - hence, we just do not send it to Bedrock. + // Since we sent the real difficulty before opening the server settings form, let's restore it to our workaround here + if (session.getWorldCache().getDifficulty() == Difficulty.PEACEFUL) { + SetDifficultyPacket setDifficultyPacket = new SetDifficultyPacket(); + setDifficultyPacket.setDifficulty(Difficulty.EASY.ordinal()); + session.sendUpstreamPacket(setDifficultyPacket); + } + } + private static String translateEntry(String key, String locale) { if (key.startsWith("%")) { // Bedrock will translate From 45f96a03e79b8227f8cd661ad08b423dda237042 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sun, 28 Jul 2024 12:56:41 -0400 Subject: [PATCH 179/233] Fix online mode no auth token dimension setting on login --- .../protocol/java/JavaLoginTranslator.java | 22 +++++++++++-------- .../geysermc/geyser/util/DimensionUtils.java | 5 +++-- 2 files changed, 16 insertions(+), 11 deletions(-) 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 641313ee4..cf4b7058b 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 @@ -26,28 +26,25 @@ package org.geysermc.geyser.translator.protocol.java; import net.kyori.adventure.key.Key; -import org.geysermc.erosion.Constants; -import org.geysermc.geyser.level.JavaDimension; -import org.geysermc.geyser.util.MinecraftKey; -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; import org.cloudburstmc.protocol.bedrock.packet.GameRulesChangedPacket; -import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; import org.cloudburstmc.protocol.bedrock.packet.SetPlayerGameTypePacket; +import org.geysermc.erosion.Constants; import org.geysermc.floodgate.pluginmessage.PluginMessageChannels; import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.entity.type.player.SessionPlayerEntity; import org.geysermc.geyser.erosion.GeyserboundHandshakePacketHandler; +import org.geysermc.geyser.level.JavaDimension; 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.geyser.util.DimensionUtils; import org.geysermc.geyser.util.EntityUtils; +import org.geysermc.geyser.util.MinecraftKey; +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 java.nio.charset.StandardCharsets; import java.util.Arrays; @@ -83,6 +80,13 @@ public class JavaLoginTranslator extends PacketTranslator Date: Mon, 29 Jul 2024 00:16:15 -0700 Subject: [PATCH 180/233] 1.21.20 Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .../geyser/impl/camera/CameraDefinitions.java | 14 +- .../geyser/network/CodecProcessor.java | 50 +- .../geysermc/geyser/network/GameProtocol.java | 19 +- .../geyser/network/UpstreamPacketHandler.java | 2 +- .../populator/BlockRegistryPopulator.java | 4 +- .../registry/populator/Conversion685_671.java | 12 +- .../registry/populator/Conversion712_685.java | 436 ++ .../populator/ItemRegistryPopulator.java | 4 +- .../inventory/InventoryTranslator.java | 4 +- .../resources/bedrock/biome_definitions.dat | Bin 41676 -> 41832 bytes .../bedrock/block_palette.1_21_20.nbt | Bin 0 -> 178977 bytes .../bedrock/creative_items.1_21_20.json | 6214 +++++++++++++++ .../resources/bedrock/entity_identifiers.dat | Bin 8314 -> 8314 bytes .../bedrock/runtime_item_states.1_21_20.json | 6794 +++++++++++++++++ core/src/main/resources/mappings | 2 +- gradle/libs.versions.toml | 2 +- 16 files changed, 13521 insertions(+), 36 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/registry/populator/Conversion712_685.java create mode 100644 core/src/main/resources/bedrock/block_palette.1_21_20.nbt create mode 100644 core/src/main/resources/bedrock/creative_items.1_21_20.json create mode 100644 core/src/main/resources/bedrock/runtime_item_states.1_21_20.json 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 index 80564bdf3..7bb25c9ef 100644 --- a/core/src/main/java/org/geysermc/geyser/impl/camera/CameraDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/impl/camera/CameraDefinitions.java @@ -43,13 +43,13 @@ public class CameraDefinitions { 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))); + new CameraPreset(CameraPerspective.FIRST_PERSON.id(), "", null, null, null, null, null, null, OptionalBoolean.empty()), + new CameraPreset(CameraPerspective.FREE.id(), "", null, null, null, null, null, null, OptionalBoolean.empty()), + new CameraPreset(CameraPerspective.THIRD_PERSON.id(), "", null, null, null, null, null, null, OptionalBoolean.empty()), + new CameraPreset(CameraPerspective.THIRD_PERSON_FRONT.id(), "", null, null, null, null, null, null, OptionalBoolean.empty()), + new CameraPreset("geyser:free_audio", "minecraft:free", null, null, null, null, null, CameraAudioListener.PLAYER, OptionalBoolean.of(false)), + new CameraPreset("geyser:free_effects", "minecraft:free", null, null, null, null, null, CameraAudioListener.CAMERA, OptionalBoolean.of(true)), + new CameraPreset("geyser:free_audio_effects", "minecraft:free", null, null, null, null, null, CameraAudioListener.PLAYER, OptionalBoolean.of(true))); SimpleDefinitionRegistry.Builder builder = SimpleDefinitionRegistry.builder(); for (int i = 0; i < CAMERA_PRESETS.size(); i++) { 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 e7cf81d47..fd18c01ce 100644 --- a/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java +++ b/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java @@ -40,6 +40,9 @@ import org.cloudburstmc.protocol.bedrock.codec.v407.serializer.InventorySlotSeri 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.codec.v712.serializer.InventoryContentSerializer_v712; +import org.cloudburstmc.protocol.bedrock.codec.v712.serializer.InventorySlotSerializer_v712; +import org.cloudburstmc.protocol.bedrock.codec.v712.serializer.MobArmorEquipmentSerializer_v712; import org.cloudburstmc.protocol.bedrock.packet.AnvilDamagePacket; import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket; import org.cloudburstmc.protocol.bedrock.packet.BossEventPacket; @@ -119,7 +122,17 @@ class CodecProcessor { /** * 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() { + private static final BedrockPacketSerializer INVENTORY_CONTENT_SERIALIZER_V407 = 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 InventoryContentPacket since server-auth inventory is used. + */ + private static final BedrockPacketSerializer INVENTORY_CONTENT_SERIALIZER_V712 = new InventoryContentSerializer_v712() { @Override public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, InventoryContentPacket packet) { throw new IllegalArgumentException("Client cannot send InventoryContentPacket in server-auth inventory environment!"); @@ -129,7 +142,17 @@ class CodecProcessor { /** * 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() { + private static final BedrockPacketSerializer INVENTORY_SLOT_SERIALIZER_V407 = 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 throws an exception when trying to deserialize InventorySlotPacket since server-auth inventory is used. + */ + private static final BedrockPacketSerializer INVENTORY_SLOT_SERIALIZER_V712 = new InventorySlotSerializer_v712() { @Override public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, InventorySlotPacket packet) { throw new IllegalArgumentException("Client cannot send InventorySlotPacket in server-auth inventory environment!"); @@ -148,7 +171,16 @@ class CodecProcessor { /** * 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() { + private static final BedrockPacketSerializer MOB_ARMOR_EQUIPMENT_SERIALIZER_V291 = new MobArmorEquipmentSerializer_v291() { + @Override + public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, MobArmorEquipmentPacket 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_V712 = new MobArmorEquipmentSerializer_v712() { @Override public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, MobArmorEquipmentPacket packet) { } @@ -193,7 +225,7 @@ class CodecProcessor { /** * 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() { + private static final BedrockPacketSerializer SET_ENTITY_MOTION_SERIALIZER = new SetEntityMotionSerializer_v662() { @Override public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, SetEntityMotionPacket packet) { } @@ -224,6 +256,8 @@ class CodecProcessor { @SuppressWarnings("unchecked") static BedrockCodec processCodec(BedrockCodec codec) { + boolean isPre712 = codec.getProtocolVersion() < 712; + BedrockCodec.Builder codecBuilder = codec.toBuilder() // Illegal unused serverbound EDU packets .updateSerializer(PhotoTransferPacket.class, ILLEGAL_SERIALIZER) @@ -252,15 +286,15 @@ class CodecProcessor { .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) + .updateSerializer(InventoryContentPacket.class, isPre712 ? INVENTORY_CONTENT_SERIALIZER_V407 : INVENTORY_CONTENT_SERIALIZER_V712) + .updateSerializer(InventorySlotPacket.class, isPre712 ? INVENTORY_SLOT_SERIALIZER_V407 : INVENTORY_SLOT_SERIALIZER_V712) // Ignored only when serverbound .updateSerializer(BossEventPacket.class, BOSS_EVENT_SERIALIZER) - .updateSerializer(MobArmorEquipmentPacket.class, MOB_ARMOR_EQUIPMENT_SERIALIZER) + .updateSerializer(MobArmorEquipmentPacket.class, isPre712 ? MOB_ARMOR_EQUIPMENT_SERIALIZER_V291 : MOB_ARMOR_EQUIPMENT_SERIALIZER_V712) .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_V662) + .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) 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 8f3f00021..18dee94e6 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,8 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; import org.cloudburstmc.protocol.bedrock.codec.v671.Bedrock_v671; import org.cloudburstmc.protocol.bedrock.codec.v685.Bedrock_v685; +import org.cloudburstmc.protocol.bedrock.codec.v686.Bedrock_v686; +import org.cloudburstmc.protocol.bedrock.codec.v712.Bedrock_v712; import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodec; @@ -43,17 +45,13 @@ import java.util.StringJoiner; */ public final class GameProtocol { - // Surprise protocol bump WOW - private static final BedrockCodec BEDROCK_V686 = Bedrock_v685.CODEC.toBuilder() - .protocolVersion(686) - .minecraftVersion("1.21.2") - .build(); - /** * 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_V686); + public static final BedrockCodec DEFAULT_BEDROCK_CODEC = CodecProcessor.processCodec(Bedrock_v712.CODEC.toBuilder() + .minecraftVersion("1.21.20") + .build()); /** * A list of all supported Bedrock versions that can join Geyser @@ -73,9 +71,10 @@ public final class GameProtocol { SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v685.CODEC.toBuilder() .minecraftVersion("1.21.0/1.21.1") .build())); - SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC.toBuilder() - .minecraftVersion("1.21.2/1.21.3") - .build()); + SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v686.CODEC.toBuilder() + .minecraftVersion("1.21.2") + .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 f56a8a43f..e9c979b0c 100644 --- a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java @@ -209,7 +209,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { ResourcePackManifest.Header header = pack.manifest().header(); resourcePacksInfo.getResourcePackInfos().add(new ResourcePacksInfoPacket.Entry( header.uuid().toString(), header.version().toString(), codec.size(), pack.contentKey(), - "", header.uuid().toString(), false, false)); + "", header.uuid().toString(), false, false, false)); } resourcePacksInfo.setForcedToAccept(GeyserImpl.getInstance().getConfig().isForceResourcePacks()); session.sendUpstreamPacket(resourcePacksInfo); 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 d7dc989da..33c2bc97b 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 @@ -38,6 +38,7 @@ import it.unimi.dsi.fastutil.objects.*; import org.cloudburstmc.nbt.*; import org.cloudburstmc.protocol.bedrock.codec.v671.Bedrock_v671; import org.cloudburstmc.protocol.bedrock.codec.v685.Bedrock_v685; +import org.cloudburstmc.protocol.bedrock.codec.v712.Bedrock_v712; import org.cloudburstmc.protocol.bedrock.data.BlockPropertyData; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.geysermc.geyser.GeyserImpl; @@ -108,7 +109,8 @@ public final class BlockRegistryPopulator { private static void registerBedrockBlocks() { var blockMappers = ImmutableMap., Remapper>builder() .put(ObjectIntPair.of("1_20_80", Bedrock_v671.CODEC.getProtocolVersion()), Conversion685_671::remapBlock) - .put(ObjectIntPair.of("1_21_0", Bedrock_v685.CODEC.getProtocolVersion()), tag -> tag) + .put(ObjectIntPair.of("1_21_0", Bedrock_v685.CODEC.getProtocolVersion()), Conversion712_685::remapBlock) + .put(ObjectIntPair.of("1_21_20", Bedrock_v712.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/Conversion685_671.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion685_671.java index 58886ca57..0c7f540bf 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion685_671.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion685_671.java @@ -45,6 +45,8 @@ public class Conversion685_671 { private static final List NEW_MUSIC_DISCS = List.of(Items.MUSIC_DISC_CREATOR, Items.MUSIC_DISC_CREATOR_MUSIC_BOX, Items.MUSIC_DISC_PRECIPICE); static GeyserMappingItem remapItem(Item item, GeyserMappingItem mapping) { + mapping = Conversion712_685.remapItem(item, mapping); + String identifer = mapping.getBedrockIdentifier(); if (NEW_MUSIC_DISCS.contains(item)) { @@ -111,6 +113,8 @@ public class Conversion685_671 { } static NbtMap remapBlock(NbtMap tag) { + tag = Conversion712_685.remapBlock(tag); + final String name = tag.getString("name"); if (!MODIFIED_BLOCKS.contains(name)) { @@ -130,7 +134,7 @@ public class Conversion685_671 { String coralColor; boolean deadBit = name.startsWith("minecraft:dead_"); - switch(name) { + switch (name) { case "minecraft:tube_coral_block", "minecraft:dead_tube_coral_block" -> coralColor = "blue"; case "minecraft:brain_coral_block", "minecraft:dead_brain_coral_block" -> coralColor = "pink"; case "minecraft:bubble_coral_block", "minecraft:dead_bubble_coral_block" -> coralColor = "purple"; @@ -152,7 +156,7 @@ public class Conversion685_671 { replacement = "minecraft:double_plant"; String doublePlantType; - switch(name) { + switch (name) { case "minecraft:sunflower" -> doublePlantType = "sunflower"; case "minecraft:lilac" -> doublePlantType = "syringa"; case "minecraft:tall_grass" -> doublePlantType = "grass"; @@ -174,7 +178,7 @@ public class Conversion685_671 { replacement = "minecraft:stone_block_slab"; String stoneSlabType; - switch(name) { + switch (name) { case "minecraft:smooth_stone_slab" -> stoneSlabType = "smooth_stone"; case "minecraft:sandstone_slab" -> stoneSlabType = "sandstone"; case "minecraft:petrified_oak_slab" -> stoneSlabType = "wood"; @@ -198,7 +202,7 @@ public class Conversion685_671 { replacement = "minecraft:tallgrass"; String tallGrassType; - switch(name) { + switch (name) { case "minecraft:short_grass" -> tallGrassType = "tall"; case "minecraft:fern" -> tallGrassType = "fern"; default -> throw new IllegalStateException("Unexpected value: " + name); diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion712_685.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion712_685.java new file mode 100644 index 000000000..557a38f1f --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion712_685.java @@ -0,0 +1,436 @@ +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 Conversion712_685 { + private static final List NEW_STONE_BLOCK_SLABS_2 = List.of("minecraft:prismarine_slab", "minecraft:dark_prismarine_slab", "minecraft:smooth_sandstone_slab", "minecraft:purpur_slab", "minecraft:red_nether_brick_slab", "minecraft:prismarine_brick_slab", "minecraft:mossy_cobblestone_slab", "minecraft:red_sandstone_slab"); + private static final List NEW_STONE_BLOCK_SLABS_3 = List.of("minecraft:smooth_red_sandstone_slab", "minecraft:polished_granite_slab", "minecraft:granite_slab", "minecraft:polished_diorite_slab", "minecraft:andesite_slab", "minecraft:polished_andesite_slab", "minecraft:diorite_slab", "minecraft:end_stone_brick_slab"); + private static final List NEW_STONE_BLOCK_SLABS_4 = List.of("minecraft:smooth_quartz_slab", "minecraft:cut_sandstone_slab", "minecraft:cut_red_sandstone_slab", "minecraft:normal_stone_slab", "minecraft:mossy_stone_brick_slab"); + private static final List NEW_DOUBLE_STONE_BLOCK_SLABS = List.of("minecraft:quartz_double_slab", "minecraft:petrified_oak_double_slab", "minecraft:stone_brick_double_slab", "minecraft:brick_double_slab", "minecraft:sandstone_double_slab", "minecraft:nether_brick_double_slab", "minecraft:cobblestone_double_slab", "minecraft:smooth_stone_double_slab"); + private static final List NEW_DOUBLE_STONE_BLOCK_SLABS_2 = List.of("minecraft:prismarine_double_slab", "minecraft:dark_prismarine_double_slab", "minecraft:smooth_sandstone_double_slab", "minecraft:purpur_double_slab", "minecraft:red_nether_brick_double_slab", "minecraft:prismarine_brick_double_slab", "minecraft:mossy_cobblestone_double_slab", "minecraft:red_sandstone_double_slab"); + private static final List NEW_DOUBLE_STONE_BLOCK_SLABS_3 = List.of("minecraft:smooth_red_sandstone_double_slab", "minecraft:polished_granite_double_slab", "minecraft:granite_double_slab", "minecraft:polished_diorite_double_slab", "minecraft:andesite_double_slab", "minecraft:polished_andesite_double_slab", "minecraft:diorite_double_slab", "minecraft:end_stone_brick_double_slab"); + private static final List NEW_DOUBLE_STONE_BLOCK_SLABS_4 = List.of("minecraft:smooth_quartz_double_slab", "minecraft:cut_sandstone_double_slab", "minecraft:cut_red_sandstone_double_slab", "minecraft:normal_stone_double_slab", "minecraft:mossy_stone_brick_double_slab"); + private static final List NEW_PRISMARINE_BLOCKS = List.of("minecraft:prismarine_bricks", "minecraft:dark_prismarine", "minecraft:prismarine"); + private static final List NEW_CORAL_FAN_HANGS = List.of("minecraft:tube_coral_wall_fan", "minecraft:brain_coral_wall_fan", "minecraft:dead_tube_coral_wall_fan", "minecraft:dead_brain_coral_wall_fan"); + private static final List NEW_CORAL_FAN_HANGS_2 = List.of("minecraft:bubble_coral_wall_fan", "minecraft:fire_coral_wall_fan", "minecraft:dead_bubble_coral_wall_fan", "minecraft:dead_fire_coral_wall_fan"); + private static final List NEW_CORAL_FAN_HANGS_3 = List.of("minecraft:horn_coral_wall_fan", "minecraft:dead_horn_coral_wall_fan"); + private static final List NEW_MONSTER_EGGS = List.of("minecraft:infested_cobblestone", "minecraft:infested_stone_bricks", "minecraft:infested_mossy_stone_bricks", "minecraft:infested_cracked_stone_bricks", "minecraft:infested_chiseled_stone_bricks", "minecraft:infested_stone"); + private static final List NEW_STONEBRICK_BLOCKS = List.of("minecraft:mossy_stone_bricks", "minecraft:cracked_stone_bricks", "minecraft:chiseled_stone_bricks", "minecraft:smooth_stone_bricks", "minecraft:stone_bricks"); + private static final List NEW_LIGHT_BLOCKS = List.of("minecraft:light_block_0", "minecraft:light_block_1", "minecraft:light_block_2", "minecraft:light_block_3", "minecraft:light_block_4", "minecraft:light_block_5", "minecraft:light_block_6", "minecraft:light_block_7", "minecraft:light_block_8", "minecraft:light_block_9", "minecraft:light_block_10", "minecraft:light_block_11", "minecraft:light_block_12", "minecraft:light_block_13", "minecraft:light_block_14", "minecraft:light_block_15"); + private static final List NEW_SANDSTONE_BLOCKS = List.of("minecraft:cut_sandstone", "minecraft:chiseled_sandstone", "minecraft:smooth_sandstone", "minecraft:sandstone"); + private static final List NEW_QUARTZ_BLOCKS = List.of("minecraft:chiseled_quartz_block", "minecraft:quartz_pillar", "minecraft:smooth_quartz", "minecraft:quartz_block"); + private static final List NEW_RED_SANDSTONE_BLOCKS = List.of("minecraft:cut_red_sandstone", "minecraft:chiseled_red_sandstone", "minecraft:smooth_red_sandstone", "minecraft:red_sandstone"); + private static final List NEW_SAND_BLOCKS = List.of("minecraft:red_sand", "minecraft:sand"); + private static final List NEW_DIRT_BLOCKS = List.of("minecraft:coarse_dirt", "minecraft:dirt"); + private static final List NEW_ANVILS = List.of("minecraft:damaged_anvil", "minecraft:chipped_anvil", "minecraft:deprecated_anvil", "minecraft:anvil"); + private static final List NEW_YELLOW_FLOWERS = List.of("minecraft:dandelion"); + private static final List NEW_BLOCKS = Stream.of(NEW_STONE_BLOCK_SLABS_2, NEW_STONE_BLOCK_SLABS_3, NEW_STONE_BLOCK_SLABS_4, NEW_DOUBLE_STONE_BLOCK_SLABS, NEW_DOUBLE_STONE_BLOCK_SLABS_2, NEW_DOUBLE_STONE_BLOCK_SLABS_3, NEW_DOUBLE_STONE_BLOCK_SLABS_4, NEW_PRISMARINE_BLOCKS, NEW_CORAL_FAN_HANGS, NEW_CORAL_FAN_HANGS_2, NEW_CORAL_FAN_HANGS_3, NEW_MONSTER_EGGS, NEW_STONEBRICK_BLOCKS, NEW_LIGHT_BLOCKS, NEW_SANDSTONE_BLOCKS, NEW_QUARTZ_BLOCKS, NEW_RED_SANDSTONE_BLOCKS, NEW_SAND_BLOCKS, NEW_DIRT_BLOCKS, NEW_ANVILS, NEW_YELLOW_FLOWERS).flatMap(List::stream).toList(); + + static GeyserMappingItem remapItem(Item item, GeyserMappingItem mapping) { + String identifer = mapping.getBedrockIdentifier(); + + if (!NEW_BLOCKS.contains(identifer)) { + return mapping; + } + + if (identifer.equals("minecraft:coarse_dirt")) { + return mapping.withBedrockIdentifier("minecraft:dirt").withBedrockData(1); + } + + if (identifer.equals("minecraft:dandelion")) { + return mapping.withBedrockIdentifier("minecraft:yellow_flower").withBedrockData(0); + } + + if (identifer.equals("minecraft:red_sand")) { + return mapping.withBedrockIdentifier("minecraft:sand").withBedrockData(1); + } + + if (NEW_PRISMARINE_BLOCKS.contains(identifer)) { + switch (identifer) { + case "minecraft:prismarine" -> { return mapping.withBedrockIdentifier("minecraft:prismarine").withBedrockData(0); } + case "minecraft:dark_prismarine" -> { return mapping.withBedrockIdentifier("minecraft:prismarine").withBedrockData(1); } + case "minecraft:prismarine_bricks" -> { return mapping.withBedrockIdentifier("minecraft:prismarine").withBedrockData(2); } + } + } + + if (NEW_SANDSTONE_BLOCKS.contains(identifer)) { + switch (identifer) { + case "minecraft:sandstone" -> { return mapping.withBedrockIdentifier("minecraft:sandstone").withBedrockData(0); } + case "minecraft:chiseled_sandstone" -> { return mapping.withBedrockIdentifier("minecraft:sandstone").withBedrockData(1); } + case "minecraft:cut_sandstone" -> { return mapping.withBedrockIdentifier("minecraft:sandstone").withBedrockData(2); } + case "minecraft:smooth_sandstone" -> { return mapping.withBedrockIdentifier("minecraft:sandstone").withBedrockData(3); } + } + } + + if (NEW_RED_SANDSTONE_BLOCKS.contains(identifer)) { + switch (identifer) { + case "minecraft:red_sandstone" -> { return mapping.withBedrockIdentifier("minecraft:red_sandstone").withBedrockData(0); } + case "minecraft:chiseled_red_sandstone" -> { return mapping.withBedrockIdentifier("minecraft:red_sandstone").withBedrockData(1); } + case "minecraft:cut_red_sandstone" -> { return mapping.withBedrockIdentifier("minecraft:red_sandstone").withBedrockData(2); } + case "minecraft:smooth_red_sandstone" -> { return mapping.withBedrockIdentifier("minecraft:red_sandstone").withBedrockData(3); } + } + } + + if (NEW_QUARTZ_BLOCKS.contains(identifer)) { + switch (identifer) { + case "minecraft:quartz_block" -> { return mapping.withBedrockIdentifier("minecraft:quartz_block").withBedrockData(0); } + case "minecraft:chiseled_quartz_block" -> { return mapping.withBedrockIdentifier("minecraft:quartz_block").withBedrockData(1); } + case "minecraft:quartz_pillar" -> { return mapping.withBedrockIdentifier("minecraft:quartz_block").withBedrockData(2); } + case "minecraft:smooth_quartz" -> { return mapping.withBedrockIdentifier("minecraft:quartz_block").withBedrockData(3); } + } + } + + if (NEW_STONE_BLOCK_SLABS_2.contains(identifer)) { + switch (identifer) { + case "minecraft:red_sandstone_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab2").withBedrockData(0); } + case "minecraft:purpur_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab2").withBedrockData(1); } + case "minecraft:prismarine_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab2").withBedrockData(2); } + case "minecraft:dark_prismarine_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab2").withBedrockData(3); } + case "minecraft:prismarine_brick_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab2").withBedrockData(4); } + case "minecraft:mossy_cobblestone_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab2").withBedrockData(5); } + case "minecraft:smooth_sandstone_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab2").withBedrockData(6); } + case "minecraft:red_nether_brick_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab2").withBedrockData(7); } + } + } + + if (NEW_STONE_BLOCK_SLABS_3.contains(identifer)) { + switch (identifer) { + case "minecraft:end_stone_brick_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab3").withBedrockData(0); } + case "minecraft:smooth_red_sandstone_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab3").withBedrockData(1); } + case "minecraft:polished_andesite_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab3").withBedrockData(2); } + case "minecraft:andesite_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab3").withBedrockData(3); } + case "minecraft:diorite_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab3").withBedrockData(4); } + case "minecraft:polished_diorite_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab3").withBedrockData(5); } + case "minecraft:granite_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab3").withBedrockData(6); } + case "minecraft:polished_granite_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab3").withBedrockData(7); } + } + } + + if (NEW_STONE_BLOCK_SLABS_4.contains(identifer)) { + switch (identifer) { + case "minecraft:mossy_stone_brick_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab4").withBedrockData(0); } + case "minecraft:smooth_quartz_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab4").withBedrockData(1); } + case "minecraft:normal_stone_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab4").withBedrockData(2); } + case "minecraft:cut_sandstone_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab4").withBedrockData(3); } + case "minecraft:cut_red_sandstone_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab4").withBedrockData(4); } + } + } + + if (NEW_MONSTER_EGGS.contains(identifer)) { + switch (identifer) { + case "minecraft:infested_stone" -> { return mapping.withBedrockIdentifier("minecraft:monster_egg").withBedrockData(0); } + case "minecraft:infested_cobblestone" -> { return mapping.withBedrockIdentifier("minecraft:monster_egg").withBedrockData(1); } + case "minecraft:infested_stone_bricks" -> { return mapping.withBedrockIdentifier("minecraft:monster_egg").withBedrockData(2); } + case "minecraft:infested_mossy_stone_bricks" -> { return mapping.withBedrockIdentifier("minecraft:monster_egg").withBedrockData(3); } + case "minecraft:infested_cracked_stone_bricks" -> { return mapping.withBedrockIdentifier("minecraft:monster_egg").withBedrockData(4); } + case "minecraft:infested_chiseled_stone_bricks" -> { return mapping.withBedrockIdentifier("minecraft:monster_egg").withBedrockData(5); } + } + } + + if (NEW_STONEBRICK_BLOCKS.contains(identifer)) { + switch (identifer) { + case "minecraft:stone_bricks" -> { return mapping.withBedrockIdentifier("minecraft:stonebrick").withBedrockData(0); } + case "minecraft:mossy_stone_bricks" -> { return mapping.withBedrockIdentifier("minecraft:stonebrick").withBedrockData(1); } + case "minecraft:cracked_stone_bricks" -> { return mapping.withBedrockIdentifier("minecraft:stonebrick").withBedrockData(2); } + case "minecraft:chiseled_stone_bricks" -> { return mapping.withBedrockIdentifier("minecraft:stonebrick").withBedrockData(3); } + } + } + + if (NEW_ANVILS.contains(identifer)) { + switch (identifer) { + case "minecraft:anvil" -> { return mapping.withBedrockIdentifier("minecraft:anvil").withBedrockData(0); } + case "minecraft:chipped_anvil" -> { return mapping.withBedrockIdentifier("minecraft:anvil").withBedrockData(4); } + case "minecraft:damaged_anvil" -> { return mapping.withBedrockIdentifier("minecraft:anvil").withBedrockData(8); } + } + } + + return mapping; + } + + static NbtMap remapBlock(NbtMap tag) { + final String name = tag.getString("name"); + + if (!NEW_BLOCKS.contains(name)) { + return tag; + } + + String replacement; + + if (NEW_DOUBLE_STONE_BLOCK_SLABS.contains(name)) { + replacement = "minecraft:double_stone_block_slab"; + String stoneSlabType; + + switch (name) { + case "minecraft:quartz_double_slab" -> stoneSlabType = "quartz"; + case "minecraft:petrified_oak_double_slab" -> stoneSlabType = "wood"; + case "minecraft:stone_brick_double_slab" -> stoneSlabType = "stone_brick"; + case "minecraft:brick_double_slab" -> stoneSlabType = "brick"; + case "minecraft:sandstone_double_slab" -> stoneSlabType = "sandstone"; + case "minecraft:nether_brick_double_slab" -> stoneSlabType = "nether_brick"; + case "minecraft:cobblestone_double_slab" -> stoneSlabType = "cobblestone"; + case "minecraft:smooth_stone_double_slab" -> stoneSlabType = "smooth_stone"; + default -> throw new IllegalStateException("Unexpected value: " + name); + } + + NbtMap states = tag.getCompound("states") + .toBuilder() + .putString("stone_slab_type", stoneSlabType) + .build(); + + return tag.toBuilder().putString("name", replacement).putCompound("states", states).build(); + } + + if (NEW_STONE_BLOCK_SLABS_2.contains(name) || NEW_DOUBLE_STONE_BLOCK_SLABS_2.contains(name)) { + replacement = NEW_STONE_BLOCK_SLABS_2.contains(name) ? "minecraft:stone_block_slab2" : "minecraft:double_stone_block_slab2"; + String stoneSlabType2; + + switch (name) { + case "minecraft:prismarine_slab", "minecraft:prismarine_double_slab" -> stoneSlabType2 = "prismarine_rough"; + case "minecraft:dark_prismarine_slab", "minecraft:dark_prismarine_double_slab" -> stoneSlabType2 = "prismarine_dark"; + case "minecraft:smooth_sandstone_slab", "minecraft:smooth_sandstone_double_slab" -> stoneSlabType2 = "smooth_sandstone"; + case "minecraft:purpur_slab", "minecraft:purpur_double_slab" -> stoneSlabType2 = "purpur"; + case "minecraft:red_nether_brick_slab", "minecraft:red_nether_brick_double_slab" -> stoneSlabType2 = "red_nether_brick"; + case "minecraft:prismarine_brick_slab", "minecraft:prismarine_brick_double_slab" -> stoneSlabType2 = "prismarine_brick"; + case "minecraft:mossy_cobblestone_slab", "minecraft:mossy_cobblestone_double_slab" -> stoneSlabType2 = "mossy_cobblestone"; + case "minecraft:red_sandstone_slab", "minecraft:red_sandstone_double_slab" -> stoneSlabType2 = "red_sandstone"; + default -> throw new IllegalStateException("Unexpected value: " + name); + } + + NbtMap states = tag.getCompound("states") + .toBuilder() + .putString("stone_slab_type_2", stoneSlabType2) + .build(); + + return tag.toBuilder().putString("name", replacement).putCompound("states", states).build(); + } + + if (NEW_STONE_BLOCK_SLABS_3.contains(name) || NEW_DOUBLE_STONE_BLOCK_SLABS_3.contains(name)) { + replacement = NEW_STONE_BLOCK_SLABS_3.contains(name) ? "minecraft:stone_block_slab3" : "minecraft:double_stone_block_slab3"; + String stoneSlabType3; + + switch (name) { + case "minecraft:smooth_red_sandstone_slab", "minecraft:smooth_red_sandstone_double_slab" -> stoneSlabType3 = "smooth_red_sandstone"; + case "minecraft:polished_granite_slab", "minecraft:polished_granite_double_slab" -> stoneSlabType3 = "polished_granite"; + case "minecraft:granite_slab", "minecraft:granite_double_slab" -> stoneSlabType3 = "granite"; + case "minecraft:polished_diorite_slab", "minecraft:polished_diorite_double_slab" -> stoneSlabType3 = "polished_diorite"; + case "minecraft:andesite_slab", "minecraft:andesite_double_slab" -> stoneSlabType3 = "andesite"; + case "minecraft:polished_andesite_slab", "minecraft:polished_andesite_double_slab" -> stoneSlabType3 = "polished_andesite"; + case "minecraft:diorite_slab", "minecraft:diorite_double_slab" -> stoneSlabType3 = "diorite"; + case "minecraft:end_stone_brick_slab", "minecraft:end_stone_brick_double_slab" -> stoneSlabType3 = "end_stone_brick"; + default -> throw new IllegalStateException("Unexpected value: " + name); + } + + NbtMap states = tag.getCompound("states") + .toBuilder() + .putString("stone_slab_type_3", stoneSlabType3) + .build(); + + return tag.toBuilder().putString("name", replacement).putCompound("states", states).build(); + } + + if (NEW_STONE_BLOCK_SLABS_4.contains(name) || NEW_DOUBLE_STONE_BLOCK_SLABS_4.contains(name)) { + replacement = NEW_STONE_BLOCK_SLABS_4.contains(name) ? "minecraft:stone_block_slab4" : "minecraft:double_stone_block_slab4"; + String stoneSlabType4; + + switch (name) { + case "minecraft:smooth_quartz_slab", "minecraft:smooth_quartz_double_slab" -> stoneSlabType4 = "smooth_quartz"; + case "minecraft:cut_sandstone_slab", "minecraft:cut_sandstone_double_slab" -> stoneSlabType4 = "cut_sandstone"; + case "minecraft:cut_red_sandstone_slab", "minecraft:cut_red_sandstone_double_slab" -> stoneSlabType4 = "cut_red_sandstone"; + case "minecraft:normal_stone_slab", "minecraft:normal_stone_double_slab" -> stoneSlabType4 = "stone"; + case "minecraft:mossy_stone_brick_slab", "minecraft:mossy_stone_brick_double_slab" -> stoneSlabType4 = "mossy_stone_brick"; + default -> throw new IllegalStateException("Unexpected value: " + name); + } + + NbtMap states = tag.getCompound("states") + .toBuilder() + .putString("stone_slab_type_4", stoneSlabType4) + .build(); + + return tag.toBuilder().putString("name", replacement).putCompound("states", states).build(); + } + + if (NEW_PRISMARINE_BLOCKS.contains(name)) { + replacement = "minecraft:prismarine"; + String prismarineBlockType; + + switch (name) { + case "minecraft:prismarine_bricks" -> prismarineBlockType = "bricks"; + case "minecraft:dark_prismarine" -> prismarineBlockType = "dark"; + case "minecraft:prismarine" -> prismarineBlockType = "default"; + default -> throw new IllegalStateException("Unexpected value: " + name); + } + + NbtMap states = tag.getCompound("states") + .toBuilder() + .putString("prismarine_block_type", prismarineBlockType) + .build(); + + return tag.toBuilder().putString("name", replacement).putCompound("states", states).build(); + } + + if (NEW_CORAL_FAN_HANGS.contains(name) || NEW_CORAL_FAN_HANGS_2.contains(name) || NEW_CORAL_FAN_HANGS_3.contains(name)) { + replacement = NEW_CORAL_FAN_HANGS.contains(name) ? "minecraft:coral_fan_hang" : NEW_CORAL_FAN_HANGS_2.contains(name) ? "minecraft:coral_fan_hang2" : "minecraft:coral_fan_hang3"; + boolean deadBit = name.startsWith("minecraft:dead_"); + boolean coralHangTypeBit = name.contains("brain") || name.contains("fire"); + + NbtMap states = tag.getCompound("states") + .toBuilder() + .putBoolean("coral_hang_type_bit", coralHangTypeBit) + .putBoolean("dead_bit", deadBit) + .build(); + + return tag.toBuilder().putString("name", replacement).putCompound("states", states).build(); + } + + if (NEW_MONSTER_EGGS.contains(name)) { + replacement = "minecraft:monster_egg"; + String monsterEggStoneType; + + switch (name) { + case "minecraft:infested_cobblestone" -> monsterEggStoneType = "cobblestone"; + case "minecraft:infested_stone_bricks" -> monsterEggStoneType = "stone_brick"; + case "minecraft:infested_mossy_stone_bricks" -> monsterEggStoneType = "mossy_stone_brick"; + case "minecraft:infested_cracked_stone_bricks" -> monsterEggStoneType = "cracked_stone_brick"; + case "minecraft:infested_chiseled_stone_bricks" -> monsterEggStoneType = "chiseled_stone_brick"; + case "minecraft:infested_stone" -> monsterEggStoneType = "stone"; + default -> throw new IllegalStateException("Unexpected value: " + name); + } + + NbtMap states = tag.getCompound("states") + .toBuilder() + .putString("monster_egg_stone_type", monsterEggStoneType) + .build(); + + return tag.toBuilder().putString("name", replacement).putCompound("states", states).build(); + } + + if (NEW_STONEBRICK_BLOCKS.contains(name)) { + replacement = "minecraft:stonebrick"; + String stoneBrickType; + + switch (name) { + case "minecraft:mossy_stone_bricks" -> stoneBrickType = "mossy"; + case "minecraft:cracked_stone_bricks" -> stoneBrickType = "cracked"; + case "minecraft:chiseled_stone_bricks" -> stoneBrickType = "chiseled"; + case "minecraft:smooth_stone_bricks" -> stoneBrickType = "smooth"; + case "minecraft:stone_bricks" -> stoneBrickType = "default"; + default -> throw new IllegalStateException("Unexpected value: " + name); + } + + NbtMap states = tag.getCompound("states") + .toBuilder() + .putString("stone_brick_type", stoneBrickType) + .build(); + + return tag.toBuilder().putString("name", replacement).putCompound("states", states).build(); + } + + if (NEW_LIGHT_BLOCKS.contains(name)) { + replacement = "minecraft:light_block"; + int blockLightLevel = Integer.parseInt(name.split("_")[2]); + + NbtMap states = tag.getCompound("states") + .toBuilder() + .putInt("block_light_level", blockLightLevel) + .build(); + + return tag.toBuilder().putString("name", replacement).putCompound("states", states).build(); + } + + if (NEW_SANDSTONE_BLOCKS.contains(name) || NEW_RED_SANDSTONE_BLOCKS.contains(name)) { + replacement = NEW_SANDSTONE_BLOCKS.contains(name) ? "minecraft:sandstone" : "minecraft:red_sandstone"; + String sandStoneType; + + switch (name) { + case "minecraft:cut_sandstone", "minecraft:cut_red_sandstone" -> sandStoneType = "cut"; + case "minecraft:chiseled_sandstone", "minecraft:chiseled_red_sandstone" -> sandStoneType = "heiroglyphs"; + case "minecraft:smooth_sandstone", "minecraft:smooth_red_sandstone" -> sandStoneType = "smooth"; + case "minecraft:sandstone", "minecraft:red_sandstone" -> sandStoneType = "default"; + default -> throw new IllegalStateException("Unexpected value: " + name); + } + + NbtMap states = tag.getCompound("states") + .toBuilder() + .putString("sand_stone_type", sandStoneType) + .build(); + + return tag.toBuilder().putString("name", replacement).putCompound("states", states).build(); + } + + if (NEW_QUARTZ_BLOCKS.contains(name)) { + replacement = "minecraft:quartz_block"; + String chiselType; + + switch (name) { + case "minecraft:chiseled_quartz_block" -> chiselType = "chiseled"; + case "minecraft:quartz_pillar" -> chiselType = "lines"; + case "minecraft:smooth_quartz" -> chiselType = "smooth"; + case "minecraft:quartz_block" -> chiselType = "default"; + default -> throw new IllegalStateException("Unexpected value: " + name); + } + + NbtMap states = tag.getCompound("states") + .toBuilder() + .putString("chisel_type", chiselType) + .build(); + + return tag.toBuilder().putString("name", replacement).putCompound("states", states).build(); + } + + if (NEW_SAND_BLOCKS.contains(name)) { + replacement = "minecraft:sand"; + String sandType = name.equals("minecraft:red_sand") ? "red" : "normal"; + + NbtMap states = tag.getCompound("states") + .toBuilder() + .putString("sand_type", sandType) + .build(); + + return tag.toBuilder().putString("name", replacement).putCompound("states", states).build(); + } + + if (NEW_DIRT_BLOCKS.contains(name)) { + replacement = "minecraft:dirt"; + String dirtType = name.equals("minecraft:coarse_dirt") ? "coarse" : "normal"; + + NbtMap states = tag.getCompound("states") + .toBuilder() + .putString("dirt_type", dirtType) + .build(); + + return tag.toBuilder().putString("name", replacement).putCompound("states", states).build(); + } + + if (NEW_ANVILS.contains(name)) { + replacement = "minecraft:anvil"; + String damage; + + switch (name) { + case "minecraft:damaged_anvil" -> damage = "broken"; + case "minecraft:chipped_anvil" -> damage = "slightly_damaged"; + case "minecraft:deprecated_anvil" -> damage = "very_damaged"; + case "minecraft:anvil" -> damage = "undamaged"; + default -> throw new IllegalStateException("Unexpected value: " + name); + } + + NbtMap states = tag.getCompound("states") + .toBuilder() + .putString("damage", damage) + .build(); + + return tag.toBuilder().putString("name", replacement).putCompound("states", states).build(); + } + + if (NEW_YELLOW_FLOWERS.contains(name)) { + replacement = "minecraft:yellow_flower"; + return tag.toBuilder().putString("name", replacement).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 2c97fe13c..f11b58bfe 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.nbt.NbtUtils; import org.cloudburstmc.protocol.bedrock.codec.v671.Bedrock_v671; import org.cloudburstmc.protocol.bedrock.codec.v685.Bedrock_v685; +import org.cloudburstmc.protocol.bedrock.codec.v712.Bedrock_v712; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.SimpleItemDefinition; @@ -90,7 +91,8 @@ public class ItemRegistryPopulator { public static void populate() { List paletteVersions = new ArrayList<>(3); paletteVersions.add(new PaletteVersion("1_20_80", Bedrock_v671.CODEC.getProtocolVersion(), Collections.emptyMap(), Conversion685_671::remapItem)); - paletteVersions.add(new PaletteVersion("1_21_0", Bedrock_v685.CODEC.getProtocolVersion())); + paletteVersions.add(new PaletteVersion("1_21_0", Bedrock_v685.CODEC.getProtocolVersion(), Collections.emptyMap(), Conversion712_685::remapItem)); + paletteVersions.add(new PaletteVersion("1_21_20", Bedrock_v712.CODEC.getProtocolVersion())); GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap(); 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 4c426b410..ce1022936 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 @@ -894,11 +894,11 @@ public abstract class InventoryTranslator { List containerEntries = new ArrayList<>(); for (Map.Entry> entry : containerMap.entrySet()) { - containerEntries.add(new ItemStackResponseContainer(entry.getKey(), entry.getValue())); + containerEntries.add(new ItemStackResponseContainer(entry.getKey(), entry.getValue(), null)); } ItemStackResponseSlot cursorEntry = makeItemEntry(0, session.getPlayerInventory().getCursor()); - containerEntries.add(new ItemStackResponseContainer(ContainerSlotType.CURSOR, Collections.singletonList(cursorEntry))); + containerEntries.add(new ItemStackResponseContainer(ContainerSlotType.CURSOR, Collections.singletonList(cursorEntry), null)); return containerEntries; } diff --git a/core/src/main/resources/bedrock/biome_definitions.dat b/core/src/main/resources/bedrock/biome_definitions.dat index dfee570e48866c87a60fce4f93041093f7696468..3ae94a5c85c6f13d4de2feb8a5d24d2ab2f11efe 100644 GIT binary patch delta 283 zcmX?elC?gS)l wVXngD*bKkT)0^f?g3Op~DLMIErtsu-bCo7@&ljA`Yb!XJr%`9~mpLVD0G@a}7ytkO diff --git a/core/src/main/resources/bedrock/block_palette.1_21_20.nbt b/core/src/main/resources/bedrock/block_palette.1_21_20.nbt new file mode 100644 index 0000000000000000000000000000000000000000..521ea3cc6fdded8adda60e2a1ad1ff35ab826dc5 GIT binary patch literal 178977 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�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 q0AJ1OG*VR}TG|eCk Date: Mon, 29 Jul 2024 00:17:56 -0700 Subject: [PATCH 181/233] Indicate 1.21.20 support Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 07f3df5aa..ecf991cdb 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.80 - 1.21.3 and Minecraft Java 1.21 +### Currently supporting Minecraft Bedrock 1.20.80 - 1.21.20 and Minecraft Java 1.21 ## Setting Up Take a look [here](https://wiki.geysermc.org/geyser/setup/) for how to set up Geyser. From efe2736635b523564fa961ebbf3ae17011c3a8a4 Mon Sep 17 00:00:00 2001 From: chris Date: Tue, 30 Jul 2024 10:26:02 +0200 Subject: [PATCH 182/233] Fix: Piston listener on Fabric/NeoForge (#4899) * Fix: Sticky pistons not retracting on Geyser-Spigot/turning visually into normal pistons on all other platforms * Initial attempt: Mod piston listener * fix piston retracting --- bootstrap/mod/build.gradle.kts | 3 +- .../mixin/server/PistonBaseBlockMixin.java | 127 ++++++++++++++++++ .../mod/src/main/resources/geyser.mixins.json | 1 + .../populator/BlockRegistryPopulator.java | 2 +- .../level/block/entity/PistonBlockEntity.java | 5 +- .../java/level/JavaBlockEventTranslator.java | 20 ++- gradle/libs.versions.toml | 2 + 7 files changed, 148 insertions(+), 12 deletions(-) create mode 100644 bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/mixin/server/PistonBaseBlockMixin.java diff --git a/bootstrap/mod/build.gradle.kts b/bootstrap/mod/build.gradle.kts index 32224d00b..57f11b2c7 100644 --- a/bootstrap/mod/build.gradle.kts +++ b/bootstrap/mod/build.gradle.kts @@ -16,7 +16,8 @@ afterEvaluate { dependencies { api(projects.core) compileOnly(libs.mixin) + compileOnly(libs.mixinextras) // 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/src/main/java/org/geysermc/geyser/platform/mod/mixin/server/PistonBaseBlockMixin.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/mixin/server/PistonBaseBlockMixin.java new file mode 100644 index 000000000..6ac51ba52 --- /dev/null +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/mixin/server/PistonBaseBlockMixin.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 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.platform.mod.mixin.server; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.sugar.Share; +import com.llamalad7.mixinextras.sugar.ref.LocalRef; +import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.piston.PistonBaseBlock; +import net.minecraft.world.level.block.state.BlockState; +import org.cloudburstmc.math.vector.Vector3i; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.PistonCache; +import org.geysermc.geyser.translator.level.block.entity.PistonBlockEntity; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +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.HashMap; +import java.util.Map; +import java.util.UUID; + +@Mixin(PistonBaseBlock.class) +public class PistonBaseBlockMixin { + + @Shadow + @Final + private boolean isSticky; + + @ModifyExpressionValue(method = "moveBlocks", + at = @At(value = "INVOKE", target = "Lcom/google/common/collect/Maps;newHashMap()Ljava/util/HashMap;") + ) + private HashMap geyser$onMapCreate(HashMap original, @Share("pushBlocks") LocalRef> localRef) { + localRef.set(original); + return original; + } + + @Inject(method = "moveBlocks", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/piston/PistonStructureResolver;getToDestroy()Ljava/util/List;") + ) + private void geyser$onBlocksMove(Level level, BlockPos blockPos, Direction direction, boolean isExtending, CallbackInfoReturnable cir, @Share("pushBlocks") LocalRef> localRef) { + PistonValueType type = isExtending ? PistonValueType.PUSHING : PistonValueType.PULLING; + boolean sticky = this.isSticky; + + Object2ObjectMap attachedBlocks = new Object2ObjectArrayMap<>(); + boolean blocksFilled = false; + + for (Map.Entry entry : GeyserImpl.getInstance().getSessionManager().getSessions().entrySet()) { + Player player = level.getPlayerByUUID(entry.getKey()); + //noinspection resource + if (player == null || !player.level().equals(level)) { + continue; + } + GeyserSession session = entry.getValue(); + + int dX = Math.abs(blockPos.getX() - player.getBlockX()) >> 4; + int dZ = Math.abs(blockPos.getZ() - player.getBlockZ()) >> 4; + if ((dX * dX + dZ * dZ) > session.getServerRenderDistance() * session.getServerRenderDistance()) { + // Ignore pistons outside the player's render distance + continue; + } + + // Trying to grab the blocks from the world like other platforms would result in the moving piston block + // being returned instead. + if (!blocksFilled) { + Map blocks = localRef.get(); + for (Map.Entry blockStateEntry : blocks.entrySet()) { + int blockStateId = Block.BLOCK_STATE_REGISTRY.getId(blockStateEntry.getValue()); + org.geysermc.geyser.level.block.type.BlockState state = org.geysermc.geyser.level.block.type.BlockState.of(blockStateId); + attachedBlocks.put(geyser$fromBlockPos(blockStateEntry.getKey()), state); + } + blocksFilled = true; + } + + org.geysermc.geyser.level.physics.Direction orientation = org.geysermc.geyser.level.physics.Direction.VALUES[direction.ordinal()]; + + Vector3i position = geyser$fromBlockPos(blockPos); + session.executeInEventLoop(() -> { + PistonCache pistonCache = session.getPistonCache(); + PistonBlockEntity blockEntity = pistonCache.getPistons().computeIfAbsent(position, pos -> + new PistonBlockEntity(session, position, orientation, sticky, !isExtending)); + blockEntity.setAction(type, attachedBlocks); + }); + } + } + + @Unique + private static Vector3i geyser$fromBlockPos(BlockPos pos) { + return Vector3i.from(pos.getX(), pos.getY(), pos.getZ()); + } + +} diff --git a/bootstrap/mod/src/main/resources/geyser.mixins.json b/bootstrap/mod/src/main/resources/geyser.mixins.json index 2576e1ce6..e820e654d 100644 --- a/bootstrap/mod/src/main/resources/geyser.mixins.json +++ b/bootstrap/mod/src/main/resources/geyser.mixins.json @@ -5,6 +5,7 @@ "compatibilityLevel": "JAVA_17", "mixins": [ "server.BlockPlaceMixin", + "server.PistonBaseBlockMixin", "server.ServerConnectionListenerMixin" ], "server": [ 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 d7dc989da..f539e52ec 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 @@ -129,7 +129,7 @@ public final class BlockRegistryPopulator { 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.remove("network_id"); // Added in 1.19.80 builder.remove("block_id"); // Added in 1.20.60 //noinspection UnstableApiUsage builder.putCompound("states", statesInterner.intern((NbtMap) builder.remove("states"))); 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 350ce8c3e..d1dd24855 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 @@ -37,7 +37,6 @@ 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.api.util.PlatformType; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.level.block.property.Properties; @@ -230,8 +229,8 @@ public class PistonBlockEntity { BlockState state = session.getGeyser().getWorldManager().blockAt(session, blockInFront); if (state.is(Blocks.PISTON_HEAD)) { ChunkUtils.updateBlock(session, Block.JAVA_AIR_ID, blockInFront); - } else if ((session.getGeyser().getPlatformType() == PlatformType.SPIGOT || session.getErosionHandler().isActive()) && state.is(Blocks.AIR)) { - // Spigot removes the piston head from the cache, but we need to send the block update ourselves + } else if ((session.getGeyser().getWorldManager().hasOwnChunkCache() || session.getErosionHandler().isActive()) && state.is(Blocks.AIR)) { + // The platform removes the piston head from the cache, but we need to send the block update ourselves ChunkUtils.updateBlock(session, Block.JAVA_AIR_ID, blockInFront); } } 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 ff861530a..c94468c17 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 @@ -82,16 +82,22 @@ public class JavaBlockEventTranslator extends PacketTranslator new PistonBlockEntity(session, pos, direction, true, true)); + PistonBlockEntity blockEntity = pistonCache.getPistons().computeIfAbsent(position, pos -> new PistonBlockEntity(session, pos, direction, isSticky, true)); if (blockEntity.getAction() != action) { blockEntity.setAction(action, Object2ObjectMaps.emptyMap()); } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 58b5310ac..e50756ef1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -33,6 +33,7 @@ fabric-api = "0.100.1+1.21" fabric-permissions = "0.2-SNAPSHOT" neoforge-minecraft = "21.0.0-beta" mixin = "0.8.5" +mixinextras = "0.3.5" minecraft = "1.21" # plugin versions @@ -89,6 +90,7 @@ folia-api = { group = "dev.folia", name = "folia-api", version.ref = "folia" } paper-mojangapi = { group = "io.papermc.paper", name = "paper-mojangapi", version.ref = "folia" } mixin = { group = "org.spongepowered", name = "mixin", version.ref = "mixin" } +mixinextras = { module = "io.github.llamalad7:mixinextras-common", version.ref = "mixinextras" } minecraft = { group = "com.mojang", name = "minecraft", version.ref = "minecraft" } From ca0f3775a22d39617f8d9a32b983c0d187ead8ea Mon Sep 17 00:00:00 2001 From: rtm516 Date: Tue, 30 Jul 2024 13:49:42 +0100 Subject: [PATCH 183/233] Update links in README (#4917) * Update links in README * Update README.md * Update README.md --- README.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 07f3df5aa..8eac49a24 100644 --- a/README.md +++ b/README.md @@ -14,16 +14,15 @@ 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.80 - 1.21.3 and Minecraft Java 1.21 +## Supported Versions +Geyser is currently supporting Minecraft Bedrock 1.20.80 - 1.21.3 and Minecraft Java Server 1.21. For more info please see [here](https://geysermc.org/wiki/geyser/supported-versions/). ## Setting Up -Take a look [here](https://wiki.geysermc.org/geyser/setup/) for how to set up Geyser. - -[![YouTube Video](https://img.youtube.com/vi/U7dZZ8w7Gi4/0.jpg)](https://www.youtube.com/watch?v=U7dZZ8w7Gi4) +Take a look [here](https://geysermc.org/wiki/geyser/setup/) for how to set up Geyser. ## Links: - Website: https://geysermc.org -- Docs: https://wiki.geysermc.org/geyser/ +- Docs: https://geysermc.org/wiki/geyser/ - Download: https://geysermc.org/download - Discord: https://discord.gg/geysermc - Donate: https://opencollective.com/geysermc @@ -34,7 +33,7 @@ Take a look [here](https://wiki.geysermc.org/geyser/setup/) for how to set up Ge - Some Entity Flags ## 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. +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://geysermc.org/wiki/geyser/current-limitations/) page. ## Compiling 1. Clone the repo to your computer @@ -47,7 +46,7 @@ you're interested in helping out with Geyser. ## Libraries Used: - [Adventure Text Library](https://github.com/KyoriPowered/adventure) -- [NukkitX Bedrock Protocol Library](https://github.com/NukkitX/Protocol) -- [Steveice10's Java Protocol Library](https://github.com/Steveice10/MCProtocolLib) +- [CloudburstMC Bedrock Protocol Library](https://github.com/CloudburstMC/Protocol) +- [GeyserMC's Java Protocol Library](https://github.com/GeyserMC/MCProtocolLib) - [TerminalConsoleAppender](https://github.com/Minecrell/TerminalConsoleAppender) - [Simple Logging Facade for Java (slf4j)](https://github.com/qos-ch/slf4j) From 13dfc7c173550c49ff6070176f8d0c4f3d270c8a Mon Sep 17 00:00:00 2001 From: rtm516 Date: Wed, 31 Jul 2024 01:06:26 +0100 Subject: [PATCH 184/233] Allow commands with xbox achievements enabled (#4894) * Allow commands with xbox achievements enabled * Don't enable by default * Add null check to paramData * Update comment --- .../translator/protocol/java/JavaCommandsTranslator.java | 6 +++--- core/src/main/resources/config.yml | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) 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 ecfb2d220..c0e3f5716 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 @@ -169,8 +169,8 @@ public class JavaCommandsTranslator extends PacketTranslator flags = Set.of(); + // The command flags, set to NOT_CHEAT so known commands can be used while achievements are enabled. + Set flags = Set.of(CommandData.Flag.NOT_CHEAT); // Loop through all the found commands for (Map.Entry> entry : commands.entrySet()) { @@ -449,7 +449,7 @@ public class JavaCommandsTranslator extends PacketTranslator Date: Wed, 31 Jul 2024 19:21:29 +0200 Subject: [PATCH 185/233] Fix: Geyser-NeoForge not booting due to duplicate module (#4922) --- bootstrap/mod/fabric/build.gradle.kts | 5 +---- bootstrap/mod/neoforge/build.gradle.kts | 3 ++- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/bootstrap/mod/fabric/build.gradle.kts b/bootstrap/mod/fabric/build.gradle.kts index 0d083fcf7..9215c575e 100644 --- a/bootstrap/mod/fabric/build.gradle.kts +++ b/bootstrap/mod/fabric/build.gradle.kts @@ -25,10 +25,7 @@ dependencies { shadow(libs.protocol.connection) { isTransitive = false } shadow(libs.protocol.common) { isTransitive = false } shadow(libs.protocol.codec) { isTransitive = false } - shadow(libs.minecraftauth) { isTransitive = false } shadow(libs.raknet) { isTransitive = false } - - // Consequences of shading + relocating mcauthlib: shadow/relocate mcpl! shadow(libs.mcprotocollib) { isTransitive = false } // Since we also relocate cloudburst protocol: shade erosion common @@ -67,4 +64,4 @@ modrinth { dependencies { required.project("fabric-api") } -} \ No newline at end of file +} diff --git a/bootstrap/mod/neoforge/build.gradle.kts b/bootstrap/mod/neoforge/build.gradle.kts index e0e7c2dfa..741e2fd11 100644 --- a/bootstrap/mod/neoforge/build.gradle.kts +++ b/bootstrap/mod/neoforge/build.gradle.kts @@ -5,6 +5,7 @@ plugins { // This is provided by "org.cloudburstmc.math.mutable" too, so yeet. // NeoForge's class loader is *really* annoying. provided("org.cloudburstmc.math", "api") +provided("com.google.errorprone", "error_prone_annotations") architectury { platformSetupLoomIde() @@ -56,4 +57,4 @@ tasks { modrinth { loaders.add("neoforge") uploadFile.set(tasks.getByPath("remapModrinthJar")) -} \ No newline at end of file +} From 6002c9c7a167df137fb802bbbe7a38bc84de7fdb Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 31 Jul 2024 21:22:22 +0200 Subject: [PATCH 186/233] Only add a tag to the bedrock item if it is needed (#4925) --- .../java/JavaUpdateRecipesTranslator.java | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) 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 7c36c505b..689e0448a 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 @@ -49,6 +49,8 @@ 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.item.type.BedrockRequiresTagItem; +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; @@ -443,13 +445,18 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator translateShulkerBoxRecipe(GeyserShapelessRecipe recipe) { - ItemData output = ItemTranslator.translateToBedrock(session, recipe.result()); + ItemStack result = recipe.result(); + ItemData output = ItemTranslator.translateToBedrock(session, result); if (!output.isValid()) { // Likely modded item that Bedrock will complain about if it persists return null; } - // Strip NBT - tools won't appear in the recipe book otherwise - // output = output.toBuilder().tag(null).build(); // TODO confirm??? + + Item javaItem = Registries.JAVA_ITEMS.get(result.getId()); + if (!(javaItem instanceof BedrockRequiresTagItem)) { + // Strip NBT - tools won't appear in the recipe book otherwise + output = output.toBuilder().tag(null).build(); + } ItemDescriptorWithCount[][] inputCombinations = combinations(session, recipe.ingredients()); if (inputCombinations == null) { return null; @@ -467,13 +474,18 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator translateShapelessRecipe(GeyserShapelessRecipe recipe) { - ItemData output = ItemTranslator.translateToBedrock(session, recipe.result()); + ItemStack result = recipe.result(); + ItemData output = ItemTranslator.translateToBedrock(session, result); if (!output.isValid()) { // Likely modded item that Bedrock will complain about if it persists return null; } - // Strip NBT - tools won't appear in the recipe book otherwise - //output = output.toBuilder().tag(null).build(); // TODO confirm this is still true??? + + Item javaItem = Registries.JAVA_ITEMS.get(result.getId()); + if (!(javaItem instanceof BedrockRequiresTagItem)) { + // Strip NBT - tools won't appear in the recipe book otherwise + output = output.toBuilder().tag(null).build(); + } ItemDescriptorWithCount[][] inputCombinations = combinations(session, recipe.ingredients()); if (inputCombinations == null) { return null; @@ -491,13 +503,18 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator translateShapedRecipe(GeyserShapedRecipe recipe) { - ItemData output = ItemTranslator.translateToBedrock(session, recipe.result()); + ItemStack result = recipe.result(); + ItemData output = ItemTranslator.translateToBedrock(session, result); if (!output.isValid()) { // Likely modded item that Bedrock will complain about if it persists return null; } - // See above - //output = output.toBuilder().tag(null).build(); + + Item javaItem = Registries.JAVA_ITEMS.get(result.getId()); + if (!(javaItem instanceof BedrockRequiresTagItem)) { + // Strip NBT - tools won't appear in the recipe book otherwise + output = output.toBuilder().tag(null).build(); + } ItemDescriptorWithCount[][] inputCombinations = combinations(session, recipe.ingredients()); if (inputCombinations == null) { return null; From 87ab51cb28f059dc815be0c9804346d4d88535d8 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Thu, 11 Jul 2024 23:56:42 -0500 Subject: [PATCH 187/233] Cloud for commands (#3808) Co-authored-by: onebeastchris --- .../geysermc/geyser/api/command/Command.java | 133 ++++--- .../geyser/api/command/CommandSource.java | 15 + .../lifecycle/GeyserDefineCommandsEvent.java | 2 +- ...GeyserRegisterPermissionCheckersEvent.java | 42 +++ .../GeyserRegisterPermissionsEvent.java | 51 +++ .../geyser/api/extension/Extension.java | 9 + .../api/permission/PermissionChecker.java | 49 +++ bootstrap/bungeecord/build.gradle.kts | 8 +- .../bungeecord/GeyserBungeePlugin.java | 56 +-- .../GeyserBungeeUpdateListener.java | 4 +- .../command/BungeeCommandSource.java | 25 +- .../command/GeyserBungeeCommandExecutor.java | 89 ----- bootstrap/mod/fabric/build.gradle.kts | 13 +- .../fabric/GeyserFabricBootstrap.java | 33 +- bootstrap/mod/neoforge/build.gradle.kts | 11 +- .../neoforge/GeyserNeoForgeBootstrap.java | 50 ++- .../GeyserNeoForgeCommandRegistry.java | 101 ++++++ .../GeyserNeoForgePermissionHandler.java | 149 -------- .../platform/neoforge/PermissionUtils.java | 79 +++++ .../neoforge/mixin/PermissionNodeMixin.java | 48 +++ .../resources/META-INF/neoforge.mods.toml | 2 + .../resources/geyser_neoforge.mixins.json | 12 + .../platform/mod/GeyserModBootstrap.java | 75 +--- .../platform/mod/GeyserModUpdateListener.java | 13 +- .../mod/command/GeyserModCommandExecutor.java | 75 ---- ...mmandSender.java => ModCommandSource.java} | 26 +- .../mod/world/GeyserModWorldManager.java | 7 - bootstrap/spigot/build.gradle.kts | 8 +- .../platform/spigot/GeyserSpigotPlugin.java | 172 ++++----- .../spigot/GeyserSpigotUpdateListener.java | 4 +- .../command/GeyserBrigadierSupport.java | 61 ---- .../command/GeyserPaperCommandListener.java | 87 ----- .../command/GeyserSpigotCommandExecutor.java | 88 ----- ...anager.java => SpigotCommandRegistry.java} | 45 ++- .../spigot/command/SpigotCommandSource.java | 26 +- .../manager/GeyserSpigotWorldManager.java | 9 - .../spigot/src/main/resources/plugin.yml | 8 - bootstrap/standalone/build.gradle.kts | 4 + .../standalone/GeyserStandaloneBootstrap.java | 29 +- .../standalone/GeyserStandaloneLogger.java | 4 +- .../standalone/gui/GeyserStandaloneGUI.java | 20 +- bootstrap/velocity/build.gradle.kts | 9 +- .../velocity/GeyserVelocityPlugin.java | 62 ++-- .../GeyserVelocityUpdateListener.java | 4 +- .../GeyserVelocityCommandExecutor.java | 83 ----- .../command/VelocityCommandSource.java | 18 +- bootstrap/viaproxy/build.gradle.kts | 6 +- .../viaproxy/GeyserViaProxyPlugin.java | 35 +- .../geyser.modded-conventions.gradle.kts | 6 +- .../geyser.platform-conventions.gradle.kts | 1 - core/build.gradle.kts | 3 + .../java/org/geysermc/geyser/Constants.java | 2 - .../org/geysermc/geyser/GeyserBootstrap.java | 8 +- .../java/org/geysermc/geyser/GeyserImpl.java | 19 +- .../org/geysermc/geyser/GeyserLogger.java | 6 + .../java/org/geysermc/geyser/Permissions.java | 63 ++++ .../geyser/command/CommandRegistry.java | 300 ++++++++++++++++ .../command/CommandSourceConverter.java | 113 ++++++ .../geyser/command/ExceptionHandlers.java | 129 +++++++ .../geyser/command/GeyserCommand.java | 204 ++++++++--- .../geyser/command/GeyserCommandExecutor.java | 98 ------ .../geyser/command/GeyserCommandManager.java | 330 ------------------ .../geyser/command/GeyserCommandSource.java | 30 ++ .../geyser/command/GeyserPermission.java | 136 ++++++++ .../defaults/AdvancedTooltipsCommand.java | 33 +- .../command/defaults/AdvancementsCommand.java | 24 +- .../defaults/ConnectionTestCommand.java | 117 +++---- .../geyser/command/defaults/DumpCommand.java | 84 +++-- .../command/defaults/ExtensionsCommand.java | 17 +- .../geyser/command/defaults/HelpCommand.java | 76 ++-- .../geyser/command/defaults/ListCommand.java | 20 +- .../command/defaults/OffhandCommand.java | 26 +- .../command/defaults/ReloadCommand.java | 22 +- .../command/defaults/SettingsCommand.java | 27 +- .../command/defaults/StatisticsCommand.java | 27 +- .../geyser/command/defaults/StopCommand.java | 22 +- .../command/defaults/VersionCommand.java | 34 +- .../standalone/PermissionConfiguration.java | 42 +++ .../StandaloneCloudCommandManager.java | 126 +++++++ .../type/GeyserDefineCommandsEventImpl.java | 6 +- .../command/GeyserExtensionCommand.java | 195 ++++++++++- .../geyser/level/GeyserWorldManager.java | 5 - .../geysermc/geyser/level/WorldManager.java | 9 - .../loader/ProviderRegistryLoader.java | 4 +- .../geyser/session/GeyserSession.java | 28 +- .../BedrockCommandRequestTranslator.java | 26 +- .../BedrockSetDefaultGameTypeTranslator.java | 3 +- .../BedrockSetDifficultyTranslator.java | 3 +- .../BedrockSetPlayerGameTypeTranslator.java | 3 +- .../protocol/java/JavaCommandsTranslator.java | 10 +- .../org/geysermc/geyser/util/FileUtils.java | 12 + .../geysermc/geyser/util/SettingsUtils.java | 3 +- core/src/main/resources/languages | 2 +- core/src/main/resources/permissions.yml | 9 + gradle/libs.versions.toml | 13 +- 95 files changed, 2556 insertions(+), 1879 deletions(-) create mode 100644 api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserRegisterPermissionCheckersEvent.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserRegisterPermissionsEvent.java create mode 100644 api/src/main/java/org/geysermc/geyser/api/permission/PermissionChecker.java delete mode 100644 bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/command/GeyserBungeeCommandExecutor.java create mode 100644 bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeCommandRegistry.java delete 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/PermissionUtils.java create mode 100644 bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/mixin/PermissionNodeMixin.java create mode 100644 bootstrap/mod/neoforge/src/main/resources/geyser_neoforge.mixins.json delete mode 100644 bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/command/GeyserModCommandExecutor.java rename bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/command/{ModCommandSender.java => ModCommandSource.java} (77%) delete mode 100644 bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/GeyserBrigadierSupport.java delete mode 100644 bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/GeyserPaperCommandListener.java delete mode 100644 bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/GeyserSpigotCommandExecutor.java rename bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/{GeyserSpigotCommandManager.java => SpigotCommandRegistry.java} (61%) delete mode 100644 bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/command/GeyserVelocityCommandExecutor.java create mode 100644 core/src/main/java/org/geysermc/geyser/Permissions.java create mode 100644 core/src/main/java/org/geysermc/geyser/command/CommandRegistry.java create mode 100644 core/src/main/java/org/geysermc/geyser/command/CommandSourceConverter.java create mode 100644 core/src/main/java/org/geysermc/geyser/command/ExceptionHandlers.java delete mode 100644 core/src/main/java/org/geysermc/geyser/command/GeyserCommandExecutor.java delete mode 100644 core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java create mode 100644 core/src/main/java/org/geysermc/geyser/command/GeyserPermission.java create mode 100644 core/src/main/java/org/geysermc/geyser/command/standalone/PermissionConfiguration.java create mode 100644 core/src/main/java/org/geysermc/geyser/command/standalone/StandaloneCloudCommandManager.java create mode 100644 core/src/main/resources/permissions.yml diff --git a/api/src/main/java/org/geysermc/geyser/api/command/Command.java b/api/src/main/java/org/geysermc/geyser/api/command/Command.java index 2f1f2b24d..29922ae1e 100644 --- a/api/src/main/java/org/geysermc/geyser/api/command/Command.java +++ b/api/src/main/java/org/geysermc/geyser/api/command/Command.java @@ -28,7 +28,9 @@ package org.geysermc.geyser.api.command; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.api.GeyserApi; import org.geysermc.geyser.api.connection.GeyserConnection; +import org.geysermc.geyser.api.event.lifecycle.GeyserRegisterPermissionsEvent; import org.geysermc.geyser.api.extension.Extension; +import org.geysermc.geyser.api.util.TriState; import java.util.Collections; import java.util.List; @@ -58,15 +60,15 @@ public interface Command { * Gets the permission node associated with * this command. * - * @return the permission node for this command + * @return the permission node for this command if defined, otherwise an empty string */ @NonNull String permission(); /** - * Gets the aliases for this command. + * Gets the aliases for this command, as an unmodifiable list * - * @return the aliases for this command + * @return the aliases for this command as an unmodifiable list */ @NonNull List aliases(); @@ -75,35 +77,39 @@ public interface Command { * Gets if this command is designed to be used only by server operators. * * @return if this command is designated to be used only by server operators. + * @deprecated this method is not guaranteed to provide meaningful or expected results. */ - boolean isSuggestedOpOnly(); - - /** - * Gets if this command is executable on console. - * - * @return if this command is executable on console - */ - boolean isExecutableOnConsole(); - - /** - * Gets the subcommands associated with this - * command. Mainly used within the Geyser Standalone - * GUI to know what subcommands are supported. - * - * @return the subcommands associated with this command - */ - @NonNull - default List subCommands() { - return Collections.emptyList(); + @Deprecated(forRemoval = true) + default boolean isSuggestedOpOnly() { + return false; } /** - * Used to send a deny message to Java players if this command can only be used by Bedrock players. - * - * @return true if this command can only be used by Bedrock players. + * @return true if this command is executable on console + * @deprecated use {@link #isPlayerOnly()} instead (inverted) */ - default boolean isBedrockOnly() { - return false; + @Deprecated(forRemoval = true) + default boolean isExecutableOnConsole() { + return !isPlayerOnly(); + } + + /** + * @return true if this command can only be used by players + */ + boolean isPlayerOnly(); + + /** + * @return true if this command can only be used by Bedrock players + */ + boolean isBedrockOnly(); + + /** + * @deprecated this method will always return an empty immutable list + */ + @Deprecated(forRemoval = true) + @NonNull + default List subCommands() { + return Collections.emptyList(); } /** @@ -128,7 +134,7 @@ public interface Command { * is an instance of this source. * * @param sourceType the source type - * @return the builder + * @return this builder */ Builder source(@NonNull Class sourceType); @@ -136,7 +142,7 @@ public interface Command { * Sets the command name. * * @param name the command name - * @return the builder + * @return this builder */ Builder name(@NonNull String name); @@ -144,23 +150,40 @@ public interface Command { * Sets the command description. * * @param description the command description - * @return the builder + * @return this builder */ Builder description(@NonNull String description); /** - * Sets the permission node. + * Sets the permission node required to run this command.
    + * It will not be registered with any permission registries, such as an underlying server, + * or a permissions Extension (unlike {@link #permission(String, TriState)}). * * @param permission the permission node - * @return the builder + * @return this builder */ Builder permission(@NonNull String permission); + /** + * Sets the permission node and its default value. The usage of the default value is platform dependant + * and may or may not be used. For example, it may be registered to an underlying server. + *

    + * Extensions may instead listen for {@link GeyserRegisterPermissionsEvent} to register permissions, + * especially if the same permission is required by multiple commands. Also see this event for TriState meanings. + * + * @param permission the permission node + * @param defaultValue the node's default value + * @return this builder + * @deprecated this method is experimental and may be removed in the future + */ + @Deprecated + Builder permission(@NonNull String permission, @NonNull TriState defaultValue); + /** * Sets the aliases. * * @param aliases the aliases - * @return the builder + * @return this builder */ Builder aliases(@NonNull List aliases); @@ -168,46 +191,62 @@ public interface Command { * Sets if this command is designed to be used only by server operators. * * @param suggestedOpOnly if this command is designed to be used only by server operators - * @return the builder + * @return this builder + * @deprecated this method is not guaranteed to produce meaningful or expected results */ + @Deprecated(forRemoval = true) Builder suggestedOpOnly(boolean suggestedOpOnly); /** * Sets if this command is executable on console. * * @param executableOnConsole if this command is executable on console - * @return the builder + * @return this builder + * @deprecated use {@link #isPlayerOnly()} instead (inverted) */ + @Deprecated(forRemoval = true) Builder executableOnConsole(boolean executableOnConsole); + /** + * Sets if this command can only be executed by players. + * + * @param playerOnly if this command is player only + * @return this builder + */ + Builder playerOnly(boolean playerOnly); + + /** + * Sets if this command can only be executed by bedrock players. + * + * @param bedrockOnly if this command is bedrock only + * @return this builder + */ + Builder bedrockOnly(boolean bedrockOnly); + /** * Sets the subcommands. * * @param subCommands the subcommands - * @return the builder + * @return this builder + * @deprecated this method has no effect */ - Builder subCommands(@NonNull List subCommands); - - /** - * Sets if this command is bedrock only. - * - * @param bedrockOnly if this command is bedrock only - * @return the builder - */ - Builder bedrockOnly(boolean bedrockOnly); + @Deprecated(forRemoval = true) + default Builder subCommands(@NonNull List subCommands) { + return this; + } /** * Sets the {@link CommandExecutor} for this command. * * @param executor the command executor - * @return the builder + * @return this builder */ Builder executor(@NonNull CommandExecutor executor); /** * Builds the command. * - * @return the command + * @return a new command from this builder */ @NonNull Command build(); diff --git a/api/src/main/java/org/geysermc/geyser/api/command/CommandSource.java b/api/src/main/java/org/geysermc/geyser/api/command/CommandSource.java index 45276e2c4..c1453f579 100644 --- a/api/src/main/java/org/geysermc/geyser/api/command/CommandSource.java +++ b/api/src/main/java/org/geysermc/geyser/api/command/CommandSource.java @@ -26,6 +26,10 @@ package org.geysermc.geyser.api.command; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.api.connection.GeyserConnection; + +import java.util.UUID; /** * Represents an instance capable of sending commands. @@ -64,6 +68,17 @@ public interface CommandSource { */ boolean isConsole(); + /** + * @return a Java UUID if this source represents a player, otherwise null + */ + @Nullable UUID playerUuid(); + + /** + * @return a GeyserConnection if this source represents a Bedrock player that is connected + * to this Geyser instance, otherwise null + */ + @Nullable GeyserConnection connection(); + /** * Returns the locale of the command source. * 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 994373752..d136202bd 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 @@ -50,7 +50,7 @@ public interface GeyserDefineCommandsEvent extends Event { /** * Gets all the registered built-in {@link Command}s. * - * @return all the registered built-in commands + * @return all the registered built-in commands as an unmodifiable map */ @NonNull Map commands(); diff --git a/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserRegisterPermissionCheckersEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserRegisterPermissionCheckersEvent.java new file mode 100644 index 000000000..43ebc2c50 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserRegisterPermissionCheckersEvent.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.api.event.lifecycle; + +import org.geysermc.event.Event; +import org.geysermc.event.PostOrder; +import org.geysermc.geyser.api.permission.PermissionChecker; + +/** + * Fired by any permission manager implementations that wish to add support for custom permission checking. + * This event is not guaranteed to be fired - it is currently only fired on Geyser-Standalone and ViaProxy. + *

    + * Subscribing to this event with an earlier {@link PostOrder} and registering a {@link PermissionChecker} + * will result in that checker having a higher priority than others. + */ +public interface GeyserRegisterPermissionCheckersEvent extends Event { + + void register(PermissionChecker checker); +} diff --git a/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserRegisterPermissionsEvent.java b/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserRegisterPermissionsEvent.java new file mode 100644 index 000000000..4f06c4e5f --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserRegisterPermissionsEvent.java @@ -0,0 +1,51 @@ +/* + * 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.lifecycle; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.event.Event; +import org.geysermc.geyser.api.util.TriState; + +/** + * Fired by anything that wishes to gather permission nodes and defaults. + *

    + * This event is not guaranteed to be fired, as certain Geyser platforms do not have a native permission system. + * It can be expected to fire on Geyser-Spigot, Geyser-NeoForge, Geyser-Standalone, and Geyser-ViaProxy + * It may be fired by a 3rd party regardless of the platform. + */ +public interface GeyserRegisterPermissionsEvent extends Event { + + /** + * Registers a permission node and its default value with the firer.

    + * {@link TriState#TRUE} corresponds to all players having the permission by default.
    + * {@link TriState#NOT_SET} corresponds to only server operators having the permission by default (if such a concept exists on the platform).
    + * {@link TriState#FALSE} corresponds to no players having the permission by default.
    + * + * @param permission the permission node to register + * @param defaultValue the default value of the node + */ + void register(@NonNull String permission, @NonNull TriState defaultValue); +} diff --git a/api/src/main/java/org/geysermc/geyser/api/extension/Extension.java b/api/src/main/java/org/geysermc/geyser/api/extension/Extension.java index 993bdee44..1eacfea9a 100644 --- a/api/src/main/java/org/geysermc/geyser/api/extension/Extension.java +++ b/api/src/main/java/org/geysermc/geyser/api/extension/Extension.java @@ -107,6 +107,15 @@ public interface Extension extends EventRegistrar { return this.extensionLoader().description(this); } + /** + * @return the root command that all of this extension's commands will stem from. + * By default, this is the extension's id. + */ + @NonNull + default String rootCommand() { + return this.description().id(); + } + /** * Gets the extension's logger * diff --git a/api/src/main/java/org/geysermc/geyser/api/permission/PermissionChecker.java b/api/src/main/java/org/geysermc/geyser/api/permission/PermissionChecker.java new file mode 100644 index 000000000..c0d4af2f4 --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/permission/PermissionChecker.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.permission; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.api.command.CommandSource; +import org.geysermc.geyser.api.util.TriState; + +/** + * Something capable of checking if a {@link CommandSource} has a permission + */ +@FunctionalInterface +public interface PermissionChecker { + + /** + * Checks if the given source has a permission + * + * @param source the {@link CommandSource} whose permissions should be queried + * @param permission the permission node to check + * @return a {@link TriState} as the value of the node. {@link TriState#NOT_SET} generally means that the permission + * node itself was not found, and the source does not have such permission. + * {@link TriState#TRUE} and {@link TriState#FALSE} represent explicitly set values. + */ + @NonNull + TriState hasPermission(@NonNull CommandSource source, @NonNull String permission); +} diff --git a/bootstrap/bungeecord/build.gradle.kts b/bootstrap/bungeecord/build.gradle.kts index 910e50723..5fe7ea3d1 100644 --- a/bootstrap/bungeecord/build.gradle.kts +++ b/bootstrap/bungeecord/build.gradle.kts @@ -1,5 +1,7 @@ dependencies { api(projects.core) + + implementation(libs.cloud.bungee) implementation(libs.adventure.text.serializer.bungeecord) compileOnlyApi(libs.bungeecord.proxy) } @@ -8,13 +10,15 @@ platformRelocate("net.md_5.bungee.jni") platformRelocate("com.fasterxml.jackson") platformRelocate("io.netty.channel.kqueue") // This is not used because relocating breaks natives, but we must include it or else we get ClassDefNotFound platformRelocate("net.kyori") +platformRelocate("org.incendo") +platformRelocate("io.leangen.geantyref") // provided by cloud, should also be relocated platformRelocate("org.yaml") // Broken as of 1.20 // These dependencies are already present on the platform provided(libs.bungeecord.proxy) -application { - mainClass.set("org.geysermc.geyser.platform.bungeecord.GeyserBungeeMain") +tasks.withType { + manifest.attributes["Main-Class"] = "org.geysermc.geyser.platform.bungeecord.GeyserBungeeMain" } tasks.withType { 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 cd6b59f64..1c0049231 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 @@ -27,6 +27,7 @@ package org.geysermc.geyser.platform.bungeecord; import io.netty.channel.Channel; import net.md_5.bungee.BungeeCord; +import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.config.ListenerInfo; import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.protocol.ProtocolConstants; @@ -34,17 +35,20 @@ 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.command.CommandRegistry; +import org.geysermc.geyser.command.CommandSourceConverter; +import org.geysermc.geyser.command.GeyserCommandSource; 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.bungeecord.command.GeyserBungeeCommandExecutor; +import org.geysermc.geyser.platform.bungeecord.command.BungeeCommandSource; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.util.FileUtils; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.bungee.BungeeCommandManager; +import org.incendo.cloud.execution.ExecutionCoordinator; import java.io.File; import java.io.IOException; @@ -54,21 +58,22 @@ import java.net.SocketAddress; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collection; -import java.util.Map; import java.util.Optional; import java.util.UUID; import java.util.concurrent.TimeUnit; public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { - private GeyserCommandManager geyserCommandManager; + private CommandRegistry commandRegistry; private GeyserBungeeConfiguration geyserConfig; private GeyserBungeeInjector geyserInjector; private final GeyserBungeeLogger geyserLogger = new GeyserBungeeLogger(getLogger()); private IGeyserPingPassthrough geyserBungeePingPassthrough; - private GeyserImpl geyser; + // We can't disable the plugin; hence we need to keep track of it manually + private boolean disabled; + @Override public void onLoad() { onGeyserInitialize(); @@ -93,16 +98,23 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { } if (!this.loadConfig()) { + disabled = true; return; } this.geyserLogger.setDebug(geyserConfig.isDebugMode()); GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); this.geyser = GeyserImpl.load(PlatformType.BUNGEECORD, this); this.geyserInjector = new GeyserBungeeInjector(this); + + // Registration of listeners occurs only once + this.getProxy().getPluginManager().registerListener(this, new GeyserBungeeUpdateListener()); } @Override public void onEnable() { + if (disabled) { + return; // Config did not load properly! + } // 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 @@ -143,10 +155,18 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { 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(); + var sourceConverter = new CommandSourceConverter<>( + CommandSender.class, + id -> getProxy().getPlayer(id), + () -> getProxy().getConsole(), + BungeeCommandSource::new + ); + CommandManager cloud = new BungeeCommandManager<>( + this, + ExecutionCoordinator.simpleCoordinator(), + sourceConverter + ); + this.commandRegistry = new CommandRegistry(geyser, cloud, false); // applying root permission would be a breaking change because we can't register permission defaults } // Force-disable query if enabled, or else Geyser won't enable @@ -181,16 +201,6 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { } 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()) { - Map commands = entry.getValue(); - if (commands.isEmpty()) { - continue; - } - - this.getProxy().getPluginManager().registerCommand(this, new GeyserBungeeCommandExecutor(entry.getKey().description().id(), this.geyser, commands)); - } } @Override @@ -226,8 +236,8 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { } @Override - public GeyserCommandManager getGeyserCommandManager() { - return this.geyserCommandManager; + public CommandRegistry getCommandRegistry() { + return this.commandRegistry; } @Override diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeUpdateListener.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeUpdateListener.java index c68839b20..0a89b5421 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeUpdateListener.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeUpdateListener.java @@ -29,8 +29,8 @@ import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.event.PostLoginEvent; import net.md_5.bungee.api.plugin.Listener; import net.md_5.bungee.event.EventHandler; -import org.geysermc.geyser.Constants; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.Permissions; import org.geysermc.geyser.platform.bungeecord.command.BungeeCommandSource; import org.geysermc.geyser.util.VersionCheckUtils; @@ -40,7 +40,7 @@ public final class GeyserBungeeUpdateListener implements Listener { public void onPlayerJoin(final PostLoginEvent event) { if (GeyserImpl.getInstance().getConfig().isNotifyOnNewBedrockUpdate()) { final ProxiedPlayer player = event.getPlayer(); - if (player.hasPermission(Constants.UPDATE_PERMISSION)) { + if (player.hasPermission(Permissions.CHECK_UPDATE)) { VersionCheckUtils.checkForGeyserUpdate(() -> new BungeeCommandSource(player)); } } 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 e3099f170..10ccc5bac 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 @@ -27,19 +27,22 @@ package org.geysermc.geyser.platform.bungeecord.command; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer; +import net.md_5.bungee.api.CommandSender; 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.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.text.GeyserLocale; import java.util.Locale; +import java.util.UUID; public class BungeeCommandSource implements GeyserCommandSource { - private final net.md_5.bungee.api.CommandSender handle; + private final CommandSender handle; - public BungeeCommandSource(net.md_5.bungee.api.CommandSender handle) { + public BungeeCommandSource(CommandSender handle) { this.handle = handle; // Ensure even Java players' languages are loaded GeyserLocale.loadGeyserLocale(this.locale()); @@ -72,12 +75,20 @@ public class BungeeCommandSource implements GeyserCommandSource { return !(handle instanceof ProxiedPlayer); } + @Override + public @Nullable UUID playerUuid() { + if (handle instanceof ProxiedPlayer player) { + return player.getUniqueId(); + } + return null; + } + @Override public String locale() { if (handle instanceof ProxiedPlayer player) { Locale locale = player.getLocale(); if (locale != null) { - // Locale can be null early on in the conneciton + // Locale can be null early on in the connection return GeyserLocale.formatLocale(locale.getLanguage() + "_" + locale.getCountry()); } } @@ -86,6 +97,12 @@ public class BungeeCommandSource implements GeyserCommandSource { @Override public boolean hasPermission(String permission) { - return handle.hasPermission(permission); + // Handle blank permissions ourselves, as bungeecord only handles empty ones + return permission.isBlank() || handle.hasPermission(permission); + } + + @Override + public Object handle() { + return handle; } } diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/command/GeyserBungeeCommandExecutor.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/command/GeyserBungeeCommandExecutor.java deleted file mode 100644 index 2d02c9950..000000000 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/command/GeyserBungeeCommandExecutor.java +++ /dev/null @@ -1,89 +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.bungeecord.command; - -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.CommandSender; -import net.md_5.bungee.api.plugin.Command; -import net.md_5.bungee.api.plugin.TabExecutor; -import org.geysermc.geyser.GeyserImpl; -import org.geysermc.geyser.command.GeyserCommand; -import org.geysermc.geyser.command.GeyserCommandExecutor; -import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.text.GeyserLocale; - -import java.util.Arrays; -import java.util.Collections; -import java.util.Map; - -public class GeyserBungeeCommandExecutor extends Command implements TabExecutor { - private final GeyserCommandExecutor commandExecutor; - - public GeyserBungeeCommandExecutor(String name, GeyserImpl geyser, Map commands) { - super(name); - - this.commandExecutor = new GeyserCommandExecutor(geyser, commands); - } - - @Override - public void execute(CommandSender sender, String[] args) { - BungeeCommandSource commandSender = new BungeeCommandSource(sender); - GeyserSession session = this.commandExecutor.getGeyserSession(commandSender); - - if (args.length > 0) { - GeyserCommand command = this.commandExecutor.getCommand(args[0]); - if (command != null) { - if (!sender.hasPermission(command.permission())) { - String message = GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.permission_fail", commandSender.locale()); - - commandSender.sendMessage(ChatColor.RED + message); - return; - } - if (command.isBedrockOnly() && session == null) { - String message = GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.bedrock_only", commandSender.locale()); - - commandSender.sendMessage(ChatColor.RED + message); - return; - } - command.execute(session, commandSender, args.length > 1 ? Arrays.copyOfRange(args, 1, args.length) : new String[0]); - } else { - String message = GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.not_found", commandSender.locale()); - commandSender.sendMessage(ChatColor.RED + message); - } - } else { - this.commandExecutor.getCommand("help").execute(session, commandSender, new String[0]); - } - } - - @Override - public Iterable onTabComplete(CommandSender sender, String[] args) { - if (args.length == 1) { - return commandExecutor.tabComplete(new BungeeCommandSource(sender)); - } else { - return Collections.emptyList(); - } - } -} diff --git a/bootstrap/mod/fabric/build.gradle.kts b/bootstrap/mod/fabric/build.gradle.kts index 9215c575e..fd9d7e99d 100644 --- a/bootstrap/mod/fabric/build.gradle.kts +++ b/bootstrap/mod/fabric/build.gradle.kts @@ -1,7 +1,3 @@ -plugins { - application -} - architectury { platformSetupLoomIde() fabric() @@ -35,13 +31,12 @@ dependencies { shadow(projects.api) { isTransitive = false } shadow(projects.common) { isTransitive = false } - // Permissions - modImplementation(libs.fabric.permissions) - include(libs.fabric.permissions) + modImplementation(libs.cloud.fabric) + include(libs.cloud.fabric) } -application { - mainClass.set("org.geysermc.geyser.platform.fabric.GeyserFabricMain") +tasks.withType { + manifest.attributes["Main-Class"] = "org.geysermc.geyser.platform.fabric.GeyserFabricMain" } relocate("org.cloudburstmc.netty") 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 c363ade8f..149246d59 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 @@ -25,7 +25,6 @@ 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; @@ -34,9 +33,16 @@ 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.GeyserImpl; +import org.geysermc.geyser.command.CommandRegistry; +import org.geysermc.geyser.command.CommandSourceConverter; +import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.platform.mod.GeyserModBootstrap; import org.geysermc.geyser.platform.mod.GeyserModUpdateListener; +import org.geysermc.geyser.platform.mod.command.ModCommandSource; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.execution.ExecutionCoordinator; +import org.incendo.cloud.fabric.FabricServerCommandManager; public class GeyserFabricBootstrap extends GeyserModBootstrap implements ModInitializer { @@ -70,20 +76,23 @@ public class GeyserFabricBootstrap extends GeyserModBootstrap implements ModInit ServerPlayConnectionEvents.JOIN.register((handler, $, $$) -> GeyserModUpdateListener.onPlayReady(handler.getPlayer())); this.onGeyserInitialize(); + + var sourceConverter = CommandSourceConverter.layered( + CommandSourceStack.class, + id -> getServer().getPlayerList().getPlayer(id), + Player::createCommandSourceStack, + () -> getServer().createCommandSourceStack(), // NPE if method reference is used, since server is not available yet + ModCommandSource::new + ); + CommandManager cloud = new FabricServerCommandManager<>( + ExecutionCoordinator.simpleCoordinator(), + sourceConverter + ); + this.setCommandRegistry(new CommandRegistry(GeyserImpl.getInstance(), cloud, false)); // applying root permission would be a breaking change because we can't register permission defaults } @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); - } - - @Override - public boolean hasPermission(@NonNull CommandSourceStack source, @NonNull String permissionNode, int permissionLevel) { - return Permissions.check(source, permissionNode, permissionLevel); - } } diff --git a/bootstrap/mod/neoforge/build.gradle.kts b/bootstrap/mod/neoforge/build.gradle.kts index 741e2fd11..81a35a58b 100644 --- a/bootstrap/mod/neoforge/build.gradle.kts +++ b/bootstrap/mod/neoforge/build.gradle.kts @@ -1,7 +1,3 @@ -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") @@ -38,10 +34,13 @@ dependencies { // Include all transitive deps of core via JiJ includeTransitive(projects.core) + + modImplementation(libs.cloud.neoforge) + include(libs.cloud.neoforge) } -application { - mainClass.set("org.geysermc.geyser.platform.forge.GeyserNeoForgeMain") +tasks.withType { + manifest.attributes["Main-Class"] = "org.geysermc.geyser.platform.neoforge.GeyserNeoForgeMain" } tasks { 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 b97e42389..7d3b9dc5f 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,6 +27,7 @@ package org.geysermc.geyser.platform.neoforge; import net.minecraft.commands.CommandSourceStack; import net.minecraft.world.entity.player.Player; +import net.neoforged.bus.api.EventPriority; import net.neoforged.fml.ModContainer; import net.neoforged.fml.common.Mod; import net.neoforged.fml.loading.FMLLoader; @@ -35,15 +36,22 @@ 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; -import org.checkerframework.checker.nullness.qual.NonNull; +import net.neoforged.neoforge.server.permission.events.PermissionGatherEvent; +import org.geysermc.geyser.api.event.lifecycle.GeyserRegisterPermissionsEvent; +import org.geysermc.geyser.command.CommandSourceConverter; +import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.platform.mod.GeyserModBootstrap; import org.geysermc.geyser.platform.mod.GeyserModUpdateListener; +import org.geysermc.geyser.platform.mod.command.ModCommandSource; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.execution.ExecutionCoordinator; +import org.incendo.cloud.neoforge.NeoForgeServerCommandManager; + +import java.util.Objects; @Mod(ModConstants.MOD_ID) public class GeyserNeoForgeBootstrap extends GeyserModBootstrap { - private final GeyserNeoForgePermissionHandler permissionHandler = new GeyserNeoForgePermissionHandler(); - public GeyserNeoForgeBootstrap(ModContainer container) { super(new GeyserNeoForgePlatform(container)); @@ -56,9 +64,25 @@ public class GeyserNeoForgeBootstrap extends GeyserModBootstrap { NeoForge.EVENT_BUS.addListener(this::onServerStopping); NeoForge.EVENT_BUS.addListener(this::onPlayerJoin); - NeoForge.EVENT_BUS.addListener(this.permissionHandler::onPermissionGather); + + NeoForge.EVENT_BUS.addListener(EventPriority.HIGHEST, this::onPermissionGather); this.onGeyserInitialize(); + + var sourceConverter = CommandSourceConverter.layered( + CommandSourceStack.class, + id -> getServer().getPlayerList().getPlayer(id), + Player::createCommandSourceStack, + () -> getServer().createCommandSourceStack(), + ModCommandSource::new + ); + CommandManager cloud = new NeoForgeServerCommandManager<>( + ExecutionCoordinator.simpleCoordinator(), + sourceConverter + ); + GeyserNeoForgeCommandRegistry registry = new GeyserNeoForgeCommandRegistry(getGeyser(), cloud); + this.setCommandRegistry(registry); + NeoForge.EVENT_BUS.addListener(EventPriority.LOWEST, registry::onPermissionGatherForUndefined); } private void onServerStarted(ServerStartedEvent event) { @@ -87,13 +111,17 @@ public class GeyserNeoForgeBootstrap extends GeyserModBootstrap { return FMLLoader.getDist().isDedicatedServer(); } - @Override - public boolean hasPermission(@NonNull Player source, @NonNull String permissionNode) { - return this.permissionHandler.hasPermission(source, permissionNode); - } + private void onPermissionGather(PermissionGatherEvent.Nodes event) { + getGeyser().eventBus().fire( + (GeyserRegisterPermissionsEvent) (permission, defaultValue) -> { + Objects.requireNonNull(permission, "permission"); + Objects.requireNonNull(defaultValue, "permission default for " + permission); - @Override - public boolean hasPermission(@NonNull CommandSourceStack source, @NonNull String permissionNode, int permissionLevel) { - return this.permissionHandler.hasPermission(source, permissionNode, permissionLevel); + if (permission.isBlank()) { + return; + } + PermissionUtils.register(permission, defaultValue, event); + } + ); } } diff --git a/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeCommandRegistry.java b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeCommandRegistry.java new file mode 100644 index 000000000..a8854d5d9 --- /dev/null +++ b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeCommandRegistry.java @@ -0,0 +1,101 @@ +/* + * 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.platform.neoforge; + +import net.neoforged.neoforge.server.permission.events.PermissionGatherEvent; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.event.lifecycle.GeyserRegisterPermissionsEvent; +import org.geysermc.geyser.api.util.TriState; +import org.geysermc.geyser.command.CommandRegistry; +import org.geysermc.geyser.command.GeyserCommand; +import org.geysermc.geyser.command.GeyserCommandSource; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.neoforge.PermissionNotRegisteredException; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class GeyserNeoForgeCommandRegistry extends CommandRegistry { + + /** + * Permissions with an undefined permission default. Use Set to not register the same fallback more than once. + * NeoForge requires that all permissions are registered, and cloud-neoforge follows that. + * This is unlike most platforms, on which we wouldn't register a permission if no default was provided. + */ + private final Set undefinedPermissions = new HashSet<>(); + + public GeyserNeoForgeCommandRegistry(GeyserImpl geyser, CommandManager cloud) { + super(geyser, cloud); + } + + @Override + protected void register(GeyserCommand command, Map commands) { + super.register(command, commands); + + // FIRST STAGE: Collect all permissions that may have undefined defaults. + if (!command.permission().isBlank() && command.permissionDefault() == null) { + // Permission requirement exists but no default value specified. + undefinedPermissions.add(command.permission()); + } + } + + @Override + protected void onRegisterPermissions(GeyserRegisterPermissionsEvent event) { + super.onRegisterPermissions(event); + + // SECOND STAGE + // Now that we are aware of all commands, we can eliminate some incorrect assumptions. + // Example: two commands may have the same permission, but only of them defines a permission default. + undefinedPermissions.removeAll(permissionDefaults.keySet()); + } + + /** + * Registers permissions with possibly undefined defaults. + * Should be subscribed late to allow extensions and mods to register a desired permission default first. + */ + void onPermissionGatherForUndefined(PermissionGatherEvent.Nodes event) { + // THIRD STAGE + for (String permission : undefinedPermissions) { + if (PermissionUtils.register(permission, TriState.NOT_SET, event)) { + // The permission was not already registered + geyser.getLogger().debug("Registered permission " + permission + " with fallback default value of NOT_SET"); + } + } + } + + @Override + public boolean hasPermission(GeyserCommandSource source, String permission) { + // NeoForgeServerCommandManager will throw this exception if the permission is not registered to the server. + // We can't realistically ensure that every permission is registered (calls by API users), so we catch this. + // This works for our calls, but not for cloud's internal usage. For that case, see above. + try { + return super.hasPermission(source, permission); + } catch (PermissionNotRegisteredException e) { + return false; + } + } +} 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 deleted file mode 100644 index 0a5f8f052..000000000 --- a/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgePermissionHandler.java +++ /dev/null @@ -1,149 +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.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/PermissionUtils.java b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/PermissionUtils.java new file mode 100644 index 000000000..c57dc9a6c --- /dev/null +++ b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/PermissionUtils.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 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.platform.neoforge; + +import net.neoforged.neoforge.server.permission.events.PermissionGatherEvent; +import net.neoforged.neoforge.server.permission.nodes.PermissionNode; +import net.neoforged.neoforge.server.permission.nodes.PermissionTypes; +import org.geysermc.geyser.api.event.lifecycle.GeyserRegisterPermissionsEvent; +import org.geysermc.geyser.api.util.TriState; +import org.geysermc.geyser.platform.neoforge.mixin.PermissionNodeMixin; + +/** + * Common logic for handling the more complicated way we have to register permission on NeoForge + */ +public class PermissionUtils { + + private PermissionUtils() { + //no + } + + /** + * Registers the given permission and its default value to the event. If the permission has the same name as one + * that has already been registered to the event, it will not be registered. In other words, it will not override. + * + * @param permission the permission to register + * @param permissionDefault the permission's default value. See {@link GeyserRegisterPermissionsEvent#register(String, TriState)} for TriState meanings. + * @param event the registration event + * @return true if the permission was registered + */ + public static boolean register(String permission, TriState permissionDefault, PermissionGatherEvent.Nodes event) { + // NeoForge likes to crash if you try and register a duplicate node + if (event.getNodes().stream().noneMatch(n -> n.getNodeName().equals(permission))) { + PermissionNode node = createNode(permission, permissionDefault); + event.addNodes(node); + return true; + } + return false; + } + + private static PermissionNode createNode(String node, TriState permissionDefault) { + return PermissionNodeMixin.geyser$construct( + node, + PermissionTypes.BOOLEAN, + (player, playerUUID, context) -> switch (permissionDefault) { + case TRUE -> true; + case FALSE -> false; + case NOT_SET -> { + if (player != null) { + yield player.createCommandSourceStack().hasPermission(player.server.getOperatorUserPermissionLevel()); + } + yield false; // NeoForge javadocs say player is null in the case of an offline player. + } + } + ); + } +} diff --git a/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/mixin/PermissionNodeMixin.java b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/mixin/PermissionNodeMixin.java new file mode 100644 index 000000000..a43acd58a --- /dev/null +++ b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/mixin/PermissionNodeMixin.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.platform.neoforge.mixin; + +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 org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(value = PermissionNode.class, remap = false) // this is API - do not remap +public interface PermissionNodeMixin { + + /** + * Invokes the matching private constructor in {@link PermissionNode}. + *

    + * The typical constructors in PermissionNode require a mod id, which means our permission nodes + * would end up becoming {@code geyser_neoforge.} instead of just {@code }. + */ + @SuppressWarnings("rawtypes") // the varargs + @Invoker("") + static PermissionNode geyser$construct(String nodeName, PermissionType type, PermissionNode.PermissionResolver defaultResolver, PermissionDynamicContextKey... dynamics) { + throw new IllegalStateException(); + } +} diff --git a/bootstrap/mod/neoforge/src/main/resources/META-INF/neoforge.mods.toml b/bootstrap/mod/neoforge/src/main/resources/META-INF/neoforge.mods.toml index fa01bb6ec..56b7d68e1 100644 --- a/bootstrap/mod/neoforge/src/main/resources/META-INF/neoforge.mods.toml +++ b/bootstrap/mod/neoforge/src/main/resources/META-INF/neoforge.mods.toml @@ -11,6 +11,8 @@ authors="GeyserMC" description="${description}" [[mixins]] config = "geyser.mixins.json" +[[mixins]] +config = "geyser_neoforge.mixins.json" [[dependencies.geyser_neoforge]] modId="neoforge" type="required" diff --git a/bootstrap/mod/neoforge/src/main/resources/geyser_neoforge.mixins.json b/bootstrap/mod/neoforge/src/main/resources/geyser_neoforge.mixins.json new file mode 100644 index 000000000..f1653051c --- /dev/null +++ b/bootstrap/mod/neoforge/src/main/resources/geyser_neoforge.mixins.json @@ -0,0 +1,12 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "org.geysermc.geyser.platform.neoforge.mixin", + "compatibilityLevel": "JAVA_17", + "mixins": [ + "PermissionNodeMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} 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 d7373f0a9..f11b5fbd6 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 @@ -25,30 +25,21 @@ 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.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.Commands; import net.minecraft.server.MinecraftServer; -import net.minecraft.world.entity.player.Player; 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; -import org.geysermc.geyser.api.command.Command; -import org.geysermc.geyser.api.extension.Extension; -import org.geysermc.geyser.command.GeyserCommand; -import org.geysermc.geyser.command.GeyserCommandManager; +import org.geysermc.geyser.command.CommandRegistry; import org.geysermc.geyser.configuration.GeyserConfiguration; 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.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; @@ -59,7 +50,6 @@ 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; @RequiredArgsConstructor @@ -70,13 +60,15 @@ public abstract class GeyserModBootstrap implements GeyserBootstrap { private final GeyserModPlatform platform; + @Getter private GeyserImpl geyser; private Path dataFolder; - @Setter + @Setter @Getter private MinecraftServer server; - private GeyserCommandManager geyserCommandManager; + @Setter + private CommandRegistry commandRegistry; private GeyserModConfiguration geyserConfig; private GeyserModInjector geyserInjector; private final GeyserModLogger geyserLogger = new GeyserModLogger(); @@ -94,10 +86,6 @@ public abstract class GeyserModBootstrap implements GeyserBootstrap { this.geyserLogger.setDebug(geyserConfig.isDebugMode()); GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); 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(); } public void onGeyserEnable() { @@ -130,50 +118,6 @@ public abstract class GeyserModBootstrap implements GeyserBootstrap { if (isServer()) { this.geyserInjector.initializeLocalChannel(this); } - - // Start command building - // Set just "geyser" as the help command - 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()) { - 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 - .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 "/" - 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()) { - GeyserModCommandExecutor executor = new GeyserModCommandExecutor(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 @@ -206,8 +150,8 @@ public abstract class GeyserModBootstrap implements GeyserBootstrap { } @Override - public GeyserCommandManager getGeyserCommandManager() { - return geyserCommandManager; + public CommandRegistry getCommandRegistry() { + return commandRegistry; } @Override @@ -235,6 +179,7 @@ public abstract class GeyserModBootstrap implements GeyserBootstrap { return this.server.getServerVersion(); } + @SuppressWarnings("ConstantConditions") // Certain IDEA installations think that ip cannot be null @NonNull @Override public String getServerBindAddress() { @@ -270,10 +215,6 @@ public abstract class GeyserModBootstrap implements GeyserBootstrap { 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 { diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModUpdateListener.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModUpdateListener.java index 11ca0bc4f..6a724155f 100644 --- a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModUpdateListener.java +++ b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/GeyserModUpdateListener.java @@ -25,17 +25,18 @@ package org.geysermc.geyser.platform.mod; -import net.minecraft.commands.CommandSourceStack; import net.minecraft.world.entity.player.Player; -import org.geysermc.geyser.Constants; -import org.geysermc.geyser.platform.mod.command.ModCommandSender; +import org.geysermc.geyser.Permissions; +import org.geysermc.geyser.platform.mod.command.ModCommandSource; import org.geysermc.geyser.util.VersionCheckUtils; 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)); + // Should be creating this in the supplier, but we need it for the permission check. + // Not a big deal currently because ModCommandSource doesn't load locale, so don't need to try to wait for it. + ModCommandSource source = new ModCommandSource(player.createCommandSourceStack()); + if (source.hasPermission(Permissions.CHECK_UPDATE)) { + VersionCheckUtils.checkForGeyserUpdate(() -> source); } } diff --git a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/command/GeyserModCommandExecutor.java b/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/command/GeyserModCommandExecutor.java deleted file mode 100644 index 694dc732e..000000000 --- a/bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/command/GeyserModCommandExecutor.java +++ /dev/null @@ -1,75 +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.mod.command; - -import com.mojang.brigadier.Command; -import com.mojang.brigadier.context.CommandContext; -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 GeyserModCommandExecutor extends GeyserCommandExecutor implements Command { - private final GeyserCommand command; - - public GeyserModCommandExecutor(GeyserImpl geyser, GeyserCommand command) { - super(geyser, Collections.singletonMap(command.name(), command)); - this.command = command; - } - - public boolean testPermission(CommandSourceStack source) { - return GeyserModBootstrap.getInstance().hasPermission(source, command.permission(), command.isSuggestedOpOnly() ? 2 : 0); - } - - @Override - public int run(CommandContext context) { - return runWithArgs(context, ""); - } - - public int runWithArgs(CommandContext context, String args) { - CommandSourceStack source = context.getSource(); - 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())); - return 0; - } - - if (command.isBedrockOnly() && session == null) { - sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.bedrock_only", sender.locale())); - return 0; - } - - command.execute(session, sender, args.split(" ")); - return 0; - } -} 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/ModCommandSource.java similarity index 77% rename from bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/command/ModCommandSender.java rename to bootstrap/mod/src/main/java/org/geysermc/geyser/platform/mod/command/ModCommandSource.java index 5bebfae93..af1f368b3 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/ModCommandSource.java @@ -31,19 +31,21 @@ import net.minecraft.core.RegistryAccess; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; 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; +import java.util.UUID; -public class ModCommandSender implements GeyserCommandSource { +public class ModCommandSource implements GeyserCommandSource { private final CommandSourceStack source; - public ModCommandSender(CommandSourceStack source) { + public ModCommandSource(CommandSourceStack source) { this.source = source; + // todo find locale? } @Override @@ -75,8 +77,24 @@ public class ModCommandSender implements GeyserCommandSource { return !(source.getEntity() instanceof ServerPlayer); } + @Override + public @Nullable UUID playerUuid() { + if (source.getEntity() instanceof ServerPlayer player) { + return player.getUUID(); + } + return null; + } + @Override public boolean hasPermission(String permission) { - return GeyserModBootstrap.getInstance().hasPermission(source, permission, source.getServer().getOperatorUserPermissionLevel()); + // Unlike other bootstraps; we delegate to cloud here too: + // On NeoForge; we'd have to keep track of all PermissionNodes - cloud already does that + // For Fabric, we won't need to include the Fabric Permissions API anymore - cloud already does that too :p + return GeyserImpl.getInstance().commandRegistry().hasPermission(this, permission); + } + + @Override + public Object handle() { + return source; } } 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 db1768737..89452eba3 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 @@ -48,7 +48,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.vector.Vector3i; 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.MinecraftKey; import org.geysermc.mcprotocollib.protocol.data.game.Holder; @@ -111,12 +110,6 @@ public class GeyserModWorldManager extends GeyserWorldManager { return SharedConstants.getCurrentVersion().getProtocolVersion() == GameProtocol.getJavaProtocolVersion(); } - @Override - public boolean hasPermission(GeyserSession session, String permission) { - ServerPlayer player = getPlayer(session); - return GeyserModBootstrap.getInstance().hasPermission(player, permission); - } - @Override public GameMode getDefaultGameMode(GeyserSession session) { return GameMode.byId(server.getDefaultGameType().getId()); diff --git a/bootstrap/spigot/build.gradle.kts b/bootstrap/spigot/build.gradle.kts index fcb85f100..0a1271145 100644 --- a/bootstrap/spigot/build.gradle.kts +++ b/bootstrap/spigot/build.gradle.kts @@ -17,12 +17,12 @@ dependencies { classifier("all") // otherwise the unshaded jar is used without the shaded NMS implementations }) + implementation(libs.cloud.paper) implementation(libs.commodore) implementation(libs.adventure.text.serializer.bungeecord) compileOnly(libs.folia.api) - compileOnly(libs.paper.mojangapi) compileOnlyApi(libs.viaversion) } @@ -33,13 +33,15 @@ platformRelocate("com.fasterxml.jackson") platformRelocate("net.kyori", "net.kyori.adventure.text.logger.slf4j.ComponentLogger") platformRelocate("org.objectweb.asm") platformRelocate("me.lucko.commodore") +platformRelocate("org.incendo") +platformRelocate("io.leangen.geantyref") // provided by cloud, should also be relocated platformRelocate("org.yaml") // Broken as of 1.20 // These dependencies are already present on the platform provided(libs.viaversion) -application { - mainClass.set("org.geysermc.geyser.platform.spigot.GeyserSpigotMain") +tasks.withType { + manifest.attributes["Main-Class"] = "org.geysermc.geyser.platform.spigot.GeyserSpigotMain" } tasks.withType { 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 2d13155f2..3bb44a4bc 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 @@ -30,37 +30,34 @@ import com.viaversion.viaversion.api.data.MappingData; import com.viaversion.viaversion.api.protocol.ProtocolPathEntry; import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; import io.netty.buffer.ByteBuf; -import me.lucko.commodore.CommodoreProvider; import org.bukkit.Bukkit; import org.bukkit.block.data.BlockData; -import org.bukkit.command.CommandMap; -import org.bukkit.command.PluginCommand; +import org.bukkit.command.CommandSender; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.server.ServerLoadEvent; import org.bukkit.permissions.Permission; import org.bukkit.permissions.PermissionDefault; -import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; 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; +import org.geysermc.geyser.api.event.lifecycle.GeyserRegisterPermissionsEvent; import org.geysermc.geyser.api.util.PlatformType; -import org.geysermc.geyser.command.GeyserCommandManager; +import org.geysermc.geyser.command.CommandRegistry; +import org.geysermc.geyser.command.CommandSourceConverter; +import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.dump.BootstrapDumpInfo; import org.geysermc.geyser.level.WorldManager; import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough; import org.geysermc.geyser.ping.IGeyserPingPassthrough; -import org.geysermc.geyser.platform.spigot.command.GeyserBrigadierSupport; -import org.geysermc.geyser.platform.spigot.command.GeyserSpigotCommandExecutor; -import org.geysermc.geyser.platform.spigot.command.GeyserSpigotCommandManager; +import org.geysermc.geyser.platform.spigot.command.SpigotCommandRegistry; +import org.geysermc.geyser.platform.spigot.command.SpigotCommandSource; import org.geysermc.geyser.platform.spigot.world.GeyserPistonListener; import org.geysermc.geyser.platform.spigot.world.GeyserSpigotBlockPlaceListener; import org.geysermc.geyser.platform.spigot.world.manager.GeyserSpigotLegacyNativeWorldManager; @@ -68,21 +65,21 @@ 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.incendo.cloud.bukkit.BukkitCommandManager; +import org.incendo.cloud.execution.ExecutionCoordinator; +import org.incendo.cloud.paper.LegacyPaperCommandManager; import java.io.File; import java.io.IOException; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; 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; public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { - private GeyserSpigotCommandManager geyserCommandManager; + private CommandRegistry commandRegistry; private GeyserSpigotConfiguration geyserConfig; private GeyserSpigotInjector geyserInjector; private final GeyserSpigotLogger geyserLogger = GeyserPaperLogger.supported() ? @@ -165,31 +162,37 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { @Override public void onEnable() { - this.geyserCommandManager = new GeyserSpigotCommandManager(geyser); - this.geyserCommandManager.init(); - - // 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); - - 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); - } + // Create command manager early so we can add Geyser extension commands + var sourceConverter = new CommandSourceConverter<>( + CommandSender.class, + Bukkit::getPlayer, + Bukkit::getConsoleSender, + SpigotCommandSource::new + ); + LegacyPaperCommandManager cloud; + try { + // LegacyPaperCommandManager works for spigot too, see https://cloud.incendo.org/minecraft/paper + cloud = new LegacyPaperCommandManager<>( + this, + ExecutionCoordinator.simpleCoordinator(), + sourceConverter + ); + } catch (Exception e) { + throw new RuntimeException(e); } + try { + // Commodore brigadier on Spigot/Paper 1.13 - 1.18.2 + // Paper-only brigadier on 1.19+ + cloud.registerBrigadier(); + } catch (BukkitCommandManager.BrigadierInitializationException e) { + geyserLogger.debug("Failed to initialize Brigadier support: " + e.getMessage()); + } + + this.commandRegistry = new SpigotCommandRegistry(geyser, cloud); + // 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) { @@ -227,7 +230,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { } geyserLogger.debug("Spigot ping passthrough type: " + (this.geyserSpigotPingPassthrough == null ? null : this.geyserSpigotPingPassthrough.getClass())); - // Don't need to re-create the world manager/re-register commands/reinject when reloading + // Don't need to re-create the world manager/reinject when reloading if (GeyserImpl.getInstance().isReloading()) { return; } @@ -282,79 +285,40 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { geyserLogger.debug("Using default world manager."); } - 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()) { - Map commands = entry.getValue(); - if (commands.isEmpty()) { - continue; - } - - PluginCommand command = this.getCommand(entry.getKey().description().id()); - if (command == null) { - continue; - } - - command.setExecutor(new GeyserSpigotCommandExecutor(this.geyser, commands)); - } - // 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; + // Re-registering permissions without removing it throws an error + PluginManager pluginManager = Bukkit.getPluginManager(); + geyser.eventBus().fire((GeyserRegisterPermissionsEvent) (permission, def) -> { + Objects.requireNonNull(permission, "permission"); + Objects.requireNonNull(def, "permission default for " + permission); + + if (permission.isBlank()) { + return; + } + PermissionDefault permissionDefault = switch (def) { + case TRUE -> PermissionDefault.TRUE; + case FALSE -> PermissionDefault.FALSE; + case NOT_SET -> PermissionDefault.OP; + }; + + Permission existingPermission = pluginManager.getPermission(permission); + if (existingPermission != null) { + geyserLogger.debug("permission " + permission + " with default " + + existingPermission.getDefault() + " is being overridden by " + permissionDefault); + + pluginManager.removePermission(permission); } - 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)); + pluginManager.addPermission(new Permission(permission, permissionDefault)); + }); // Events cannot be unregistered - re-registering results in duplicate firings GeyserSpigotBlockPlaceListener blockPlaceListener = new GeyserSpigotBlockPlaceListener(geyser, this.geyserWorldManager); - Bukkit.getServer().getPluginManager().registerEvents(blockPlaceListener, this); + pluginManager.registerEvents(blockPlaceListener, this); - Bukkit.getServer().getPluginManager().registerEvents(new GeyserPistonListener(geyser, this.geyserWorldManager), this); + pluginManager.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); - } + pluginManager.registerEvents(new GeyserSpigotUpdateListener(), this); } @Override @@ -390,8 +354,8 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { } @Override - public GeyserCommandManager getGeyserCommandManager() { - return this.geyserCommandManager; + public CommandRegistry getCommandRegistry() { + return this.commandRegistry; } @Override diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotUpdateListener.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotUpdateListener.java index 5e3c4def8..8a8a43460 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotUpdateListener.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotUpdateListener.java @@ -29,8 +29,8 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerJoinEvent; -import org.geysermc.geyser.Constants; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.Permissions; import org.geysermc.geyser.platform.spigot.command.SpigotCommandSource; import org.geysermc.geyser.util.VersionCheckUtils; @@ -40,7 +40,7 @@ public final class GeyserSpigotUpdateListener implements Listener { public void onPlayerJoin(final PlayerJoinEvent event) { if (GeyserImpl.getInstance().getConfig().isNotifyOnNewBedrockUpdate()) { final Player player = event.getPlayer(); - if (player.hasPermission(Constants.UPDATE_PERMISSION)) { + if (player.hasPermission(Permissions.CHECK_UPDATE)) { VersionCheckUtils.checkForGeyserUpdate(() -> new SpigotCommandSource(player)); } } diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/GeyserBrigadierSupport.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/GeyserBrigadierSupport.java deleted file mode 100644 index 61900174c..000000000 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/GeyserBrigadierSupport.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.spigot.command; - -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import me.lucko.commodore.Commodore; -import me.lucko.commodore.CommodoreProvider; -import org.bukkit.Bukkit; -import org.bukkit.command.PluginCommand; -import org.geysermc.geyser.platform.spigot.GeyserSpigotPlugin; - -/** - * Needs to be a separate class so pre-1.13 loads correctly. - */ -public final class GeyserBrigadierSupport { - - public static void loadBrigadier(GeyserSpigotPlugin plugin, PluginCommand pluginCommand) { - // Enable command completions if supported - // This is beneficial because this is sent over the network and Bedrock can see it - Commodore commodore = CommodoreProvider.getCommodore(plugin); - LiteralArgumentBuilder builder = LiteralArgumentBuilder.literal("geyser"); - for (String command : plugin.getGeyserCommandManager().getCommands().keySet()) { - builder.then(LiteralArgumentBuilder.literal(command)); - } - commodore.register(pluginCommand, builder); - - try { - Class.forName("com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent"); - Bukkit.getServer().getPluginManager().registerEvents(new GeyserPaperCommandListener(), plugin); - plugin.getGeyserLogger().debug("Successfully registered AsyncPlayerSendCommandsEvent listener."); - } catch (ClassNotFoundException e) { - plugin.getGeyserLogger().debug("Not registering AsyncPlayerSendCommandsEvent listener."); - } - } - - private GeyserBrigadierSupport() { - } -} 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 deleted file mode 100644 index dcec045ab..000000000 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/GeyserPaperCommandListener.java +++ /dev/null @@ -1,87 +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.spigot.command; - -import com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent; -import com.mojang.brigadier.tree.CommandNode; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.geysermc.geyser.GeyserImpl; -import org.geysermc.geyser.api.command.Command; - -import java.net.InetSocketAddress; -import java.util.Iterator; -import java.util.Map; - -public final class GeyserPaperCommandListener implements Listener { - - @SuppressWarnings("UnstableApiUsage") - @EventHandler - 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 - if (event.isAsynchronous()) { - CommandNode geyserBrigadier = event.getCommandNode().getChild("geyser"); - if (geyserBrigadier != null) { - Player player = event.getPlayer(); - boolean isJavaPlayer = isProbablyJavaPlayer(player); - Map commands = GeyserImpl.getInstance().commandManager().getCommands(); - Iterator> it = geyserBrigadier.getChildren().iterator(); - - while (it.hasNext()) { - CommandNode subnode = it.next(); - Command command = commands.get(subnode.getName()); - if (command != null) { - if ((command.isBedrockOnly() && isJavaPlayer) || !player.hasPermission(command.permission())) { - // Remove this from the node as we don't have permission to use it - it.remove(); - } - } - } - } - } - } - - /** - * This early on, there is a rare chance that Geyser has yet to process the connection. We'll try to minimize that - * chance, though. - */ - private boolean isProbablyJavaPlayer(Player player) { - if (GeyserImpl.getInstance().connectionByUuid(player.getUniqueId()) != null) { - // For sure this is a Bedrock player - return false; - } - - if (GeyserImpl.getInstance().getConfig().isUseDirectConnection()) { - InetSocketAddress address = player.getAddress(); - if (address != null) { - return address.getPort() != 0; - } - } - return 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 deleted file mode 100644 index 6780bde17..000000000 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/GeyserSpigotCommandExecutor.java +++ /dev/null @@ -1,88 +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.spigot.command; - -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; -import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.text.GeyserLocale; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -public class GeyserSpigotCommandExecutor extends GeyserCommandExecutor implements TabExecutor { - - public GeyserSpigotCommandExecutor(GeyserImpl geyser, Map commands) { - super(geyser, commands); - } - - @Override - public boolean onCommand(@NonNull CommandSender sender, @NonNull Command command, @NonNull String label, String[] args) { - SpigotCommandSource commandSender = new SpigotCommandSource(sender); - GeyserSession session = getGeyserSession(commandSender); - - if (args.length > 0) { - GeyserCommand geyserCommand = getCommand(args[0]); - if (geyserCommand != null) { - if (!sender.hasPermission(geyserCommand.permission())) { - String message = GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.permission_fail", commandSender.locale()); - - commandSender.sendMessage(ChatColor.RED + message); - return true; - } - if (geyserCommand.isBedrockOnly() && session == null) { - sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.bedrock_only", commandSender.locale())); - return true; - } - geyserCommand.execute(session, commandSender, args.length > 1 ? Arrays.copyOfRange(args, 1, args.length) : new String[0]); - return true; - } else { - String message = GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.not_found", commandSender.locale()); - commandSender.sendMessage(ChatColor.RED + message); - } - } else { - getCommand("help").execute(session, commandSender, new String[0]); - return true; - } - return true; - } - - @Override - public List onTabComplete(@NonNull CommandSender sender, @NonNull Command command, @NonNull String label, String[] args) { - if (args.length == 1) { - return tabComplete(new SpigotCommandSource(sender)); - } - return Collections.emptyList(); - } -} diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/GeyserSpigotCommandManager.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/SpigotCommandRegistry.java similarity index 61% rename from bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/GeyserSpigotCommandManager.java rename to bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/SpigotCommandRegistry.java index 655d3be23..39496d2c6 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/GeyserSpigotCommandManager.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/SpigotCommandRegistry.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 @@ -29,16 +29,21 @@ import org.bukkit.Bukkit; import org.bukkit.Server; import org.bukkit.command.Command; import org.bukkit.command.CommandMap; +import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.GeyserImpl; -import org.geysermc.geyser.command.GeyserCommandManager; +import org.geysermc.geyser.command.CommandRegistry; +import org.geysermc.geyser.command.GeyserCommandSource; +import org.incendo.cloud.CommandManager; import java.lang.reflect.Field; -public class GeyserSpigotCommandManager extends GeyserCommandManager { +public class SpigotCommandRegistry extends CommandRegistry { - private static final CommandMap COMMAND_MAP; + private final CommandMap commandMap; + + public SpigotCommandRegistry(GeyserImpl geyser, CommandManager cloud) { + super(geyser, cloud); - static { CommandMap commandMap = null; try { // Paper-only @@ -49,24 +54,28 @@ public class GeyserSpigotCommandManager extends GeyserCommandManager { Field cmdMapField = Bukkit.getServer().getClass().getDeclaredField("commandMap"); cmdMapField.setAccessible(true); commandMap = (CommandMap) cmdMapField.get(Bukkit.getServer()); - } catch (NoSuchFieldException | IllegalAccessException ex) { - ex.printStackTrace(); + } catch (Exception ex) { + geyser.getLogger().error("Failed to get Spigot's CommandMap", ex); } } - COMMAND_MAP = commandMap; - } - - public GeyserSpigotCommandManager(GeyserImpl geyser) { - super(geyser); + this.commandMap = commandMap; } + @NonNull @Override - public String description(String command) { - Command cmd = COMMAND_MAP.getCommand(command.replace("/", "")); - return cmd != null ? cmd.getDescription() : ""; - } + public String description(@NonNull String command, @NonNull String locale) { + // check if the command is /geyser or an extension command so that we can localize the description + String description = super.description(command, locale); + if (!description.isBlank()) { + return description; + } - public static CommandMap getCommandMap() { - return COMMAND_MAP; + if (commandMap != null) { + Command cmd = commandMap.getCommand(command); + if (cmd != null) { + return cmd.getDescription(); + } + } + return ""; } } 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 365e9ad17..c1fb837c2 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 @@ -27,17 +27,21 @@ package org.geysermc.geyser.platform.spigot.command; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer; +import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Player; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.platform.spigot.PaperAdventure; import org.geysermc.geyser.text.GeyserLocale; -public class SpigotCommandSource implements GeyserCommandSource { - private final org.bukkit.command.CommandSender handle; +import java.util.UUID; - public SpigotCommandSource(org.bukkit.command.CommandSender handle) { +public class SpigotCommandSource implements GeyserCommandSource { + private final CommandSender handle; + + public SpigotCommandSource(CommandSender handle) { this.handle = handle; // Ensure even Java players' languages are loaded GeyserLocale.loadGeyserLocale(locale()); @@ -65,11 +69,24 @@ public class SpigotCommandSource implements GeyserCommandSource { handle.spigot().sendMessage(BungeeComponentSerializer.get().serialize(message)); } + @Override + public Object handle() { + return handle; + } + @Override public boolean isConsole() { return handle instanceof ConsoleCommandSender; } + @Override + public @Nullable UUID playerUuid() { + if (handle instanceof Player player) { + return player.getUniqueId(); + } + return null; + } + @SuppressWarnings("deprecation") @Override public String locale() { @@ -83,6 +100,7 @@ public class SpigotCommandSource implements GeyserCommandSource { @Override public boolean hasPermission(String permission) { - return handle.hasPermission(permission); + // Don't trust Spigot to handle blank permissions + return permission.isBlank() || handle.hasPermission(permission); } } 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 73356c4e7..6588a22a3 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 @@ -128,15 +128,6 @@ public class GeyserSpigotWorldManager extends WorldManager { return GameMode.byId(Bukkit.getDefaultGameMode().ordinal()); } - @Override - public boolean hasPermission(GeyserSession session, String permission) { - Player player = Bukkit.getPlayer(session.javaUuid()); - if (player != null) { - return player.hasPermission(permission); - } - return false; - } - @Override public @NonNull CompletableFuture<@Nullable DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addNbtData) { Player bukkitPlayer; diff --git a/bootstrap/spigot/src/main/resources/plugin.yml b/bootstrap/spigot/src/main/resources/plugin.yml index 6e81ccdb6..14e98f577 100644 --- a/bootstrap/spigot/src/main/resources/plugin.yml +++ b/bootstrap/spigot/src/main/resources/plugin.yml @@ -6,11 +6,3 @@ version: ${version} softdepend: ["ViaVersion", "floodgate"] api-version: 1.13 folia-supported: true -commands: - geyser: - description: The main command for Geyser. - usage: /geyser - permission: geyser.command -permissions: - geyser.command: - default: true diff --git a/bootstrap/standalone/build.gradle.kts b/bootstrap/standalone/build.gradle.kts index eaf895108..fd81dad63 100644 --- a/bootstrap/standalone/build.gradle.kts +++ b/bootstrap/standalone/build.gradle.kts @@ -1,5 +1,9 @@ import com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer +plugins { + application +} + val terminalConsoleVersion = "1.2.0" val jlineVersion = "3.21.0" 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 f289fa2ba..87fbbf0aa 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 @@ -42,7 +42,8 @@ import org.checkerframework.checker.nullness.qual.NonNull; 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.command.CommandRegistry; +import org.geysermc.geyser.command.standalone.StandaloneCloudCommandManager; import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.configuration.GeyserJacksonConfiguration; import org.geysermc.geyser.dump.BootstrapDumpInfo; @@ -69,7 +70,8 @@ import java.util.stream.Collectors; public class GeyserStandaloneBootstrap implements GeyserBootstrap { - private GeyserCommandManager geyserCommandManager; + private StandaloneCloudCommandManager cloud; + private CommandRegistry commandRegistry; private GeyserStandaloneConfiguration geyserConfig; private final GeyserStandaloneLogger geyserLogger = new GeyserStandaloneLogger(); private IGeyserPingPassthrough geyserPingPassthrough; @@ -222,13 +224,24 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap { geyser = GeyserImpl.load(PlatformType.STANDALONE, this); - geyserCommandManager = new GeyserCommandManager(geyser); - geyserCommandManager.init(); + boolean reloading = geyser.isReloading(); + if (!reloading) { + // Currently there would be no significant benefit of re-initializing commands. Also, we would have to unsubscribe CommandRegistry. + // Fire GeyserDefineCommandsEvent after PreInitEvent, before PostInitEvent, for consistency with other bootstraps. + cloud = new StandaloneCloudCommandManager(geyser); + commandRegistry = new CommandRegistry(geyser, cloud); + } GeyserImpl.start(); + if (!reloading) { + // Event must be fired after CommandRegistry has subscribed its listener. + // Also, the subscription for the Permissions class is created when Geyser is initialized. + cloud.fireRegisterPermissionsEvent(); + } + if (gui != null) { - gui.enableCommands(geyser.getScheduledThread(), geyserCommandManager); + gui.enableCommands(geyser.getScheduledThread(), commandRegistry); } geyserPingPassthrough = GeyserLegacyPingPassthrough.init(geyser); @@ -255,8 +268,6 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap { @Override public void onGeyserDisable() { - // We can re-register commands on standalone, so why not - GeyserImpl.getInstance().commandManager().getCommands().clear(); geyser.disable(); } @@ -277,8 +288,8 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap { } @Override - public GeyserCommandManager getGeyserCommandManager() { - return geyserCommandManager; + public CommandRegistry getCommandRegistry() { + return commandRegistry; } @Override 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 3a34920ce..21e6a5e82 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 @@ -44,7 +44,9 @@ public class GeyserStandaloneLogger extends SimpleTerminalConsole implements Gey @Override protected void runCommand(String line) { - GeyserImpl.getInstance().commandManager().runCommand(this, line); + // don't block the terminal! + GeyserImpl geyser = GeyserImpl.getInstance(); + geyser.getScheduledThread().execute(() -> geyser.commandRegistry().runCommand(this, line)); } @Override 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 b82d8cc94..4cbd178af 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 @@ -28,7 +28,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; +import org.geysermc.geyser.command.CommandRegistry; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; @@ -271,15 +271,14 @@ public class GeyserStandaloneGUI { } /** - * Enable the command input box. + * Enables the command input box. * - * @param executor the executor for running commands off the GUI thread - * @param commandManager the command manager to delegate commands to + * @param executor the executor that commands will be run on + * @param registry the command registry containing all current commands */ - public void enableCommands(ScheduledExecutorService executor, GeyserCommandManager commandManager) { + public void enableCommands(ScheduledExecutorService executor, CommandRegistry registry) { // 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); + commandListener.dispatcher = cmd -> executor.execute(() -> registry.runCommand(logger, cmd)); commandInput.setEnabled(true); commandInput.requestFocusInWindow(); } @@ -344,13 +343,14 @@ public class GeyserStandaloneGUI { private class CommandListener implements ActionListener { - private Consumer handler; + private Consumer dispatcher; @Override public void actionPerformed(ActionEvent e) { - String command = commandInput.getText(); + // the headless variant of Standalone strips trailing whitespace for us - we need to manually + String command = commandInput.getText().stripTrailing(); appendConsole(command + "\n"); // show what was run in the console - handler.accept(command); // run the command + dispatcher.accept(command); // run the command commandInput.setText(""); // clear the input } } diff --git a/bootstrap/velocity/build.gradle.kts b/bootstrap/velocity/build.gradle.kts index 4daad9784..93e0c9c93 100644 --- a/bootstrap/velocity/build.gradle.kts +++ b/bootstrap/velocity/build.gradle.kts @@ -3,12 +3,15 @@ dependencies { api(projects.core) compileOnlyApi(libs.velocity.api) + api(libs.cloud.velocity) } platformRelocate("com.fasterxml.jackson") platformRelocate("it.unimi.dsi.fastutil") platformRelocate("net.kyori.adventure.text.serializer.gson.legacyimpl") platformRelocate("org.yaml") +platformRelocate("org.incendo") +platformRelocate("io.leangen.geantyref") // provided by cloud, should also be relocated exclude("com.google.*:*") @@ -38,8 +41,8 @@ exclude("net.kyori:adventure-nbt:*") // These dependencies are already present on the platform provided(libs.velocity.api) -application { - mainClass.set("org.geysermc.geyser.platform.velocity.GeyserVelocityMain") +tasks.withType { + manifest.attributes["Main-Class"] = "org.geysermc.geyser.platform.velocity.GeyserVelocityMain" } tasks.withType { @@ -74,4 +77,4 @@ tasks.withType { modrinth { uploadFile.set(tasks.getByPath("shadowJar")) loaders.addAll("velocity") -} \ No newline at end of file +} 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 539bdadbf..868cdbf8e 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 @@ -26,7 +26,7 @@ package org.geysermc.geyser.platform.velocity; import com.google.inject.Inject; -import com.velocitypowered.api.command.CommandManager; +import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.proxy.ListenerBoundEvent; import com.velocitypowered.api.event.proxy.ProxyInitializeEvent; @@ -34,24 +34,28 @@ 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.plugin.PluginContainer; import com.velocitypowered.api.proxy.ProxyServer; import lombok.Getter; 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.command.CommandRegistry; +import org.geysermc.geyser.command.CommandSourceConverter; +import org.geysermc.geyser.command.GeyserCommandSource; 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; +import org.geysermc.geyser.platform.velocity.command.VelocityCommandSource; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.util.FileUtils; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.execution.ExecutionCoordinator; +import org.incendo.cloud.velocity.VelocityCommandManager; import org.slf4j.Logger; import java.io.File; @@ -59,29 +63,28 @@ import java.io.IOException; import java.net.SocketAddress; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.Map; 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 { private final ProxyServer proxyServer; - private final CommandManager commandManager; + private final PluginContainer container; private final GeyserVelocityLogger geyserLogger; - private GeyserCommandManager geyserCommandManager; private GeyserVelocityConfiguration geyserConfig; private GeyserVelocityInjector geyserInjector; private IGeyserPingPassthrough geyserPingPassthrough; + private CommandRegistry commandRegistry; private GeyserImpl geyser; @Getter private final Path configFolder = Paths.get("plugins/" + GeyserImpl.NAME + "-Velocity/"); @Inject - public GeyserVelocityPlugin(ProxyServer server, Logger logger, CommandManager manager) { - this.geyserLogger = new GeyserVelocityLogger(logger); + public GeyserVelocityPlugin(ProxyServer server, PluginContainer container, Logger logger) { this.proxyServer = server; - this.commandManager = manager; + this.container = container; + this.geyserLogger = new GeyserVelocityLogger(logger); } @Override @@ -117,8 +120,19 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { this.geyserLogger.setDebug(geyserConfig.isDebugMode()); GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); } else { - this.geyserCommandManager = new GeyserCommandManager(geyser); - this.geyserCommandManager.init(); + var sourceConverter = new CommandSourceConverter<>( + CommandSource.class, + id -> proxyServer.getPlayer(id).orElse(null), + proxyServer::getConsoleCommandSource, + VelocityCommandSource::new + ); + CommandManager cloud = new VelocityCommandManager<>( + container, + proxyServer, + ExecutionCoordinator.simpleCoordinator(), + sourceConverter + ); + this.commandRegistry = new CommandRegistry(geyser, cloud, false); // applying root permission would be a breaking change because we can't register permission defaults } GeyserImpl.start(); @@ -129,22 +143,10 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { this.geyserPingPassthrough = new GeyserVelocityPingPassthrough(proxyServer); } - // No need to re-register commands when reloading - if (GeyserImpl.getInstance().isReloading()) { - return; + // No need to re-register events + if (!GeyserImpl.getInstance().isReloading()) { + proxyServer.getEventManager().register(this, new GeyserVelocityUpdateListener()); } - - this.commandManager.register("geyser", new GeyserVelocityCommandExecutor(geyser, geyserCommandManager.getCommands())); - for (Map.Entry> entry : this.geyserCommandManager.extensionCommands().entrySet()) { - Map commands = entry.getValue(); - if (commands.isEmpty()) { - continue; - } - - this.commandManager.register(entry.getKey().description().id(), new GeyserVelocityCommandExecutor(this.geyser, commands)); - } - - proxyServer.getEventManager().register(this, new GeyserVelocityUpdateListener()); } @Override @@ -175,8 +177,8 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { } @Override - public GeyserCommandManager getGeyserCommandManager() { - return this.geyserCommandManager; + public CommandRegistry getCommandRegistry() { + return this.commandRegistry; } @Override diff --git a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityUpdateListener.java b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityUpdateListener.java index 31e584612..c1c88b70d 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityUpdateListener.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityUpdateListener.java @@ -28,8 +28,8 @@ package org.geysermc.geyser.platform.velocity; import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.connection.PostLoginEvent; import com.velocitypowered.api.proxy.Player; -import org.geysermc.geyser.Constants; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.Permissions; import org.geysermc.geyser.platform.velocity.command.VelocityCommandSource; import org.geysermc.geyser.util.VersionCheckUtils; @@ -39,7 +39,7 @@ public final class GeyserVelocityUpdateListener { public void onPlayerJoin(PostLoginEvent event) { if (GeyserImpl.getInstance().getConfig().isNotifyOnNewBedrockUpdate()) { final Player player = event.getPlayer(); - if (player.hasPermission(Constants.UPDATE_PERMISSION)) { + if (player.hasPermission(Permissions.CHECK_UPDATE)) { VersionCheckUtils.checkForGeyserUpdate(() -> new VelocityCommandSource(player)); } } diff --git a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/command/GeyserVelocityCommandExecutor.java b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/command/GeyserVelocityCommandExecutor.java deleted file mode 100644 index c89c35b06..000000000 --- a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/command/GeyserVelocityCommandExecutor.java +++ /dev/null @@ -1,83 +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.velocity.command; - -import com.velocitypowered.api.command.SimpleCommand; -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.ChatColor; -import org.geysermc.geyser.text.GeyserLocale; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -public class GeyserVelocityCommandExecutor extends GeyserCommandExecutor implements SimpleCommand { - - public GeyserVelocityCommandExecutor(GeyserImpl geyser, Map commands) { - super(geyser, commands); - } - - @Override - public void execute(Invocation invocation) { - GeyserCommandSource sender = new VelocityCommandSource(invocation.source()); - GeyserSession session = getGeyserSession(sender); - - if (invocation.arguments().length > 0) { - GeyserCommand command = getCommand(invocation.arguments()[0]); - if (command != null) { - if (!invocation.source().hasPermission(getCommand(invocation.arguments()[0]).permission())) { - sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.permission_fail", sender.locale())); - return; - } - if (command.isBedrockOnly() && session == null) { - sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.bedrock_only", sender.locale())); - return; - } - command.execute(session, sender, invocation.arguments().length > 1 ? Arrays.copyOfRange(invocation.arguments(), 1, invocation.arguments().length) : new String[0]); - } else { - String message = GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.not_found", sender.locale()); - sender.sendMessage(ChatColor.RED + message); - } - } else { - getCommand("help").execute(session, sender, new String[0]); - } - } - - @Override - public List suggest(Invocation invocation) { - // Velocity seems to do the splitting a bit differently. This results in the same behaviour in bungeecord/spigot. - if (invocation.arguments().length == 0 || invocation.arguments().length == 1) { - return tabComplete(new VelocityCommandSource(invocation.source())); - } - return Collections.emptyList(); - } -} 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 403e4cb20..2240f9988 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 @@ -31,10 +31,12 @@ 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.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.text.GeyserLocale; import java.util.Locale; +import java.util.UUID; public class VelocityCommandSource implements GeyserCommandSource { @@ -72,6 +74,14 @@ public class VelocityCommandSource implements GeyserCommandSource { return handle instanceof ConsoleCommandSource; } + @Override + public @Nullable UUID playerUuid() { + if (handle instanceof Player player) { + return player.getUniqueId(); + } + return null; + } + @Override public String locale() { if (handle instanceof Player) { @@ -83,6 +93,12 @@ public class VelocityCommandSource implements GeyserCommandSource { @Override public boolean hasPermission(String permission) { - return handle.hasPermission(permission); + // Handle blank permissions ourselves, as velocity only handles empty ones + return permission.isBlank() || handle.hasPermission(permission); + } + + @Override + public Object handle() { + return handle; } } diff --git a/bootstrap/viaproxy/build.gradle.kts b/bootstrap/viaproxy/build.gradle.kts index 6eadc790f..254787743 100644 --- a/bootstrap/viaproxy/build.gradle.kts +++ b/bootstrap/viaproxy/build.gradle.kts @@ -8,12 +8,14 @@ platformRelocate("net.kyori") platformRelocate("org.yaml") platformRelocate("it.unimi.dsi.fastutil") platformRelocate("org.cloudburstmc.netty") +platformRelocate("org.incendo") +platformRelocate("io.leangen.geantyref") // provided by cloud, should also be relocated // These dependencies are already present on the platform provided(libs.viaproxy) -application { - mainClass.set("org.geysermc.geyser.platform.viaproxy.GeyserViaProxyMain") +tasks.withType { + manifest.attributes["Main-Class"] = "org.geysermc.geyser.platform.viaproxy.GeyserViaProxyMain" } tasks.withType { 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 bdc80335a..1eed778f2 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 @@ -34,13 +34,15 @@ 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.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.api.event.EventRegistrar; import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.api.util.PlatformType; -import org.geysermc.geyser.command.GeyserCommandManager; +import org.geysermc.geyser.command.CommandRegistry; +import org.geysermc.geyser.command.standalone.StandaloneCloudCommandManager; import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.dump.BootstrapDumpInfo; import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough; @@ -50,7 +52,6 @@ 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; @@ -66,7 +67,8 @@ public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserBootst private final GeyserViaProxyLogger logger = new GeyserViaProxyLogger(LogManager.getLogger("Geyser")); private GeyserViaProxyConfiguration config; private GeyserImpl geyser; - private GeyserCommandManager commandManager; + private StandaloneCloudCommandManager cloud; + private CommandRegistry commandRegistry; private IGeyserPingPassthrough pingPassthrough; @Override @@ -87,7 +89,9 @@ public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserBootst @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()))) { + CommandRegistry registry = this.getCommandRegistry(); + if (registry.rootCommands().contains(command)) { + registry.runCommand(this.getGeyserLogger(), command + " " + String.join(" ", event.getArgs())); event.setCancelled(true); } } @@ -128,17 +132,25 @@ public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserBootst @Override public void onGeyserEnable() { - if (GeyserImpl.getInstance().isReloading()) { + boolean reloading = geyser.isReloading(); + if (reloading) { if (!this.loadConfig()) { return; } + } else { + // Only initialized once - documented in the Geyser-Standalone bootstrap + this.cloud = new StandaloneCloudCommandManager(geyser); + this.commandRegistry = new CommandRegistry(geyser, cloud); } - this.commandManager = new GeyserCommandManager(this.geyser); - this.commandManager.init(); - GeyserImpl.start(); + if (!reloading) { + // Event must be fired after CommandRegistry has subscribed its listener. + // Also, the subscription for the Permissions class is created when Geyser is initialized (by GeyserImpl#start) + this.cloud.fireRegisterPermissionsEvent(); + } + 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); @@ -166,8 +178,8 @@ public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserBootst } @Override - public GeyserCommandManager getGeyserCommandManager() { - return this.commandManager; + public CommandRegistry getCommandRegistry() { + return this.commandRegistry; } @Override @@ -185,7 +197,7 @@ public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserBootst return new GeyserViaProxyDumpInfo(); } - @NotNull + @NonNull @Override public String getServerBindAddress() { if (ViaProxy.getConfig().getBindAddress() instanceof InetSocketAddress socketAddress) { @@ -209,6 +221,7 @@ public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserBootst return false; } + @SuppressWarnings("BooleanMethodIsAlwaysInverted") 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); 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 7952bcf14..20d14c443 100644 --- a/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts @@ -37,6 +37,10 @@ provided("io.netty", "netty-resolver-dns") provided("io.netty", "netty-resolver-dns-native-macos") provided("org.ow2.asm", "asm") +// cloud-fabric/cloud-neoforge jij's all cloud depends already +provided("org.incendo", ".*") +provided("io.leangen.geantyref", "geantyref") + architectury { minecraft = libs.minecraft.get().version as String } @@ -120,4 +124,4 @@ repositories { maven("https://oss.sonatype.org/content/repositories/snapshots/") maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") maven("https://maven.neoforged.net/releases") -} \ No newline at end of file +} diff --git a/build-logic/src/main/kotlin/geyser.platform-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.platform-conventions.gradle.kts index 81d224906..410e67404 100644 --- a/build-logic/src/main/kotlin/geyser.platform-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.platform-conventions.gradle.kts @@ -1,4 +1,3 @@ plugins { - application id("geyser.publish-conventions") } \ No newline at end of file diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 3b5cc3df9..acd6c5147 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -51,6 +51,9 @@ dependencies { // Adventure text serialization api(libs.bundles.adventure) + // command library + api(libs.cloud.core) + api(libs.erosion.common) { isTransitive = false } diff --git a/core/src/main/java/org/geysermc/geyser/Constants.java b/core/src/main/java/org/geysermc/geyser/Constants.java index 534cb30ad..7f00075d8 100644 --- a/core/src/main/java/org/geysermc/geyser/Constants.java +++ b/core/src/main/java/org/geysermc/geyser/Constants.java @@ -35,9 +35,7 @@ public final class Constants { public static final String NEWS_PROJECT_NAME = "geyser"; public static final String FLOODGATE_DOWNLOAD_LOCATION = "https://geysermc.org/download#floodgate"; - public static final String GEYSER_DOWNLOAD_LOCATION = "https://geysermc.org/download"; - public static final String UPDATE_PERMISSION = "geyser.update"; @Deprecated static final String SAVED_REFRESH_TOKEN_FILE = "saved-refresh-tokens.json"; diff --git a/core/src/main/java/org/geysermc/geyser/GeyserBootstrap.java b/core/src/main/java/org/geysermc/geyser/GeyserBootstrap.java index a9414d9d0..3063fa4f6 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserBootstrap.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserBootstrap.java @@ -27,7 +27,7 @@ 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.command.CommandRegistry; import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.dump.BootstrapDumpInfo; import org.geysermc.geyser.level.GeyserWorldManager; @@ -82,11 +82,11 @@ public interface GeyserBootstrap { GeyserLogger getGeyserLogger(); /** - * Returns the current CommandManager + * Returns the current CommandRegistry * - * @return The current CommandManager + * @return The current CommandRegistry */ - GeyserCommandManager getGeyserCommandManager(); + CommandRegistry getCommandRegistry(); /** * Returns the current PingPassthrough manager diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 8f88f5b6a..464ebda96 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -68,7 +68,7 @@ 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.command.CommandRegistry; import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.erosion.UnixSocketClientListener; @@ -128,7 +128,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; @Getter -public class GeyserImpl implements GeyserApi { +public class GeyserImpl implements GeyserApi, EventRegistrar { public static final ObjectMapper JSON_MAPPER = new ObjectMapper() .enable(JsonParser.Feature.IGNORE_UNDEFINED) .enable(JsonParser.Feature.ALLOW_COMMENTS) @@ -231,9 +231,7 @@ public class GeyserImpl implements GeyserApi { logger.info(GeyserLocale.getLocaleStringLog("geyser.core.load", NAME, VERSION)); logger.info(""); if (IS_DEV) { - // TODO cloud use language string - //logger.info(GeyserLocale.getLocaleStringLog("geyser.core.dev_build", "https://discord.gg/geysermc")); - logger.info("You are running a development build of Geyser! Please report any bugs you find on our Discord server: %s".formatted("https://discord.gg/geysermc")); + logger.info(GeyserLocale.getLocaleStringLog("geyser.core.dev_build", "https://discord.gg/geysermc")); logger.info(""); } logger.info("******************************************"); @@ -266,6 +264,9 @@ public class GeyserImpl implements GeyserApi { CompletableFuture.runAsync(AssetUtils::downloadAndRunClientJarTasks); }); + // Register our general permissions when possible + eventBus.subscribe(this, GeyserRegisterPermissionsEvent.class, Permissions::register); + startInstance(); GeyserConfiguration config = bootstrap.getGeyserConfig(); @@ -730,7 +731,6 @@ public class GeyserImpl implements GeyserApi { if (isEnabled) { this.disable(); } - this.commandManager().getCommands().clear(); // Disable extensions, fire the shutdown event this.eventBus.fire(new GeyserShutdownEvent(this.extensionManager, this.eventBus)); @@ -768,9 +768,12 @@ public class GeyserImpl implements GeyserApi { return this.extensionManager; } + /** + * @return the current CommandRegistry in use. The instance may change over the lifecycle of the Geyser runtime. + */ @NonNull - public GeyserCommandManager commandManager() { - return this.bootstrap.getGeyserCommandManager(); + public CommandRegistry commandRegistry() { + return this.bootstrap.getCommandRegistry(); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/GeyserLogger.java b/core/src/main/java/org/geysermc/geyser/GeyserLogger.java index aa79e3630..f408de29c 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserLogger.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserLogger.java @@ -30,6 +30,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.geyser.command.GeyserCommandSource; +import java.util.UUID; public interface GeyserLogger extends GeyserCommandSource { @@ -129,6 +130,11 @@ public interface GeyserLogger extends GeyserCommandSource { return true; } + @Override + default @Nullable UUID playerUuid() { + return null; + } + @Override default boolean hasPermission(String permission) { return true; diff --git a/core/src/main/java/org/geysermc/geyser/Permissions.java b/core/src/main/java/org/geysermc/geyser/Permissions.java new file mode 100644 index 000000000..b65a5af7a --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/Permissions.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 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; + +import org.geysermc.geyser.api.event.lifecycle.GeyserRegisterPermissionsEvent; +import org.geysermc.geyser.api.util.TriState; + +import java.util.HashMap; +import java.util.Map; + +/** + * Permissions related to Geyser + */ +public final class Permissions { + private static final Map PERMISSIONS = new HashMap<>(); + + public static final String CHECK_UPDATE = register("geyser.update"); + public static final String SERVER_SETTINGS = register("geyser.settings.server"); + public static final String SETTINGS_GAMERULES = register("geyser.settings.gamerules"); + + private Permissions() { + //no + } + + private static String register(String permission) { + return register(permission, TriState.NOT_SET); + } + + @SuppressWarnings("SameParameterValue") + private static String register(String permission, TriState permissionDefault) { + PERMISSIONS.put(permission, permissionDefault); + return permission; + } + + public static void register(GeyserRegisterPermissionsEvent event) { + for (Map.Entry permission : PERMISSIONS.entrySet()) { + event.register(permission.getKey(), permission.getValue()); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/command/CommandRegistry.java b/core/src/main/java/org/geysermc/geyser/command/CommandRegistry.java new file mode 100644 index 000000000..f07092afd --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/command/CommandRegistry.java @@ -0,0 +1,300 @@ +/* + * 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.command; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.command.Command; +import org.geysermc.geyser.api.event.EventRegistrar; +import org.geysermc.geyser.api.event.lifecycle.GeyserDefineCommandsEvent; +import org.geysermc.geyser.api.event.lifecycle.GeyserRegisterPermissionsEvent; +import org.geysermc.geyser.api.extension.Extension; +import org.geysermc.geyser.api.util.PlatformType; +import org.geysermc.geyser.api.util.TriState; +import org.geysermc.geyser.command.defaults.AdvancedTooltipsCommand; +import org.geysermc.geyser.command.defaults.AdvancementsCommand; +import org.geysermc.geyser.command.defaults.ConnectionTestCommand; +import org.geysermc.geyser.command.defaults.DumpCommand; +import org.geysermc.geyser.command.defaults.ExtensionsCommand; +import org.geysermc.geyser.command.defaults.HelpCommand; +import org.geysermc.geyser.command.defaults.ListCommand; +import org.geysermc.geyser.command.defaults.OffhandCommand; +import org.geysermc.geyser.command.defaults.ReloadCommand; +import org.geysermc.geyser.command.defaults.SettingsCommand; +import org.geysermc.geyser.command.defaults.StatisticsCommand; +import org.geysermc.geyser.command.defaults.StopCommand; +import org.geysermc.geyser.command.defaults.VersionCommand; +import org.geysermc.geyser.event.type.GeyserDefineCommandsEventImpl; +import org.geysermc.geyser.extension.command.GeyserExtensionCommand; +import org.geysermc.geyser.text.GeyserLocale; +import org.incendo.cloud.Command.Builder; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.execution.ExecutionCoordinator; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import static org.geysermc.geyser.command.GeyserCommand.DEFAULT_ROOT_COMMAND; + +/** + * Registers all built-in and extension commands to the given Cloud CommandManager. + *

    + * Fires {@link GeyserDefineCommandsEvent} upon construction. + *

    + * Subscribes to {@link GeyserRegisterPermissionsEvent} upon construction. + * A new instance of this class (that registers the same permissions) shouldn't be created until the previous + * instance is unsubscribed from the event. + */ +public class CommandRegistry implements EventRegistrar { + + private static final String GEYSER_ROOT_PERMISSION = "geyser.command"; + + protected final GeyserImpl geyser; + private final CommandManager cloud; + private final boolean applyRootPermission; + + /** + * Map of Geyser subcommands to their Commands + */ + private final Map commands = new Object2ObjectOpenHashMap<>(13); + + /** + * Map of Extensions to maps of their subcommands + */ + private final Map> extensionCommands = new Object2ObjectOpenHashMap<>(0); + + /** + * Map of root commands (that are for extensions) to Extensions + */ + private final Map extensionRootCommands = new Object2ObjectOpenHashMap<>(0); + + /** + * Map containing only permissions that have been registered with a default value + */ + protected final Map permissionDefaults = new Object2ObjectOpenHashMap<>(13); + + /** + * Creates a new CommandRegistry. Does apply a root permission. If undesired, use the other constructor. + */ + public CommandRegistry(GeyserImpl geyser, CommandManager cloud) { + this(geyser, cloud, true); + } + + /** + * Creates a new CommandRegistry + * + * @param geyser the Geyser instance + * @param cloud the cloud command manager to register commands to + * @param applyRootPermission true if this registry should apply a permission to Geyser and Extension root commands. + * This currently exists because we want to retain the root command permission for Spigot, + * but don't want to add it yet to platforms like Velocity where we cannot natively + * specify a permission default. Doing so will break setups as players would suddenly not + * have the required permission to execute any Geyser commands. + */ + public CommandRegistry(GeyserImpl geyser, CommandManager cloud, boolean applyRootPermission) { + this.geyser = geyser; + this.cloud = cloud; + this.applyRootPermission = applyRootPermission; + + // register our custom exception handlers + ExceptionHandlers.register(cloud); + + // begin command registration + HelpCommand help = new HelpCommand(DEFAULT_ROOT_COMMAND, "help", "geyser.commands.help.desc", "geyser.command.help", this.commands); + registerBuiltInCommand(help); + buildRootCommand(GEYSER_ROOT_PERMISSION, help); // build root and delegate to help + + registerBuiltInCommand(new ListCommand(geyser, "list", "geyser.commands.list.desc", "geyser.command.list")); + registerBuiltInCommand(new ReloadCommand(geyser, "reload", "geyser.commands.reload.desc", "geyser.command.reload")); + registerBuiltInCommand(new OffhandCommand("offhand", "geyser.commands.offhand.desc", "geyser.command.offhand")); + registerBuiltInCommand(new DumpCommand(geyser, "dump", "geyser.commands.dump.desc", "geyser.command.dump")); + registerBuiltInCommand(new VersionCommand(geyser, "version", "geyser.commands.version.desc", "geyser.command.version")); + registerBuiltInCommand(new SettingsCommand("settings", "geyser.commands.settings.desc", "geyser.command.settings")); + registerBuiltInCommand(new StatisticsCommand("statistics", "geyser.commands.statistics.desc", "geyser.command.statistics")); + registerBuiltInCommand(new AdvancementsCommand("advancements", "geyser.commands.advancements.desc", "geyser.command.advancements")); + registerBuiltInCommand(new AdvancedTooltipsCommand("tooltips", "geyser.commands.advancedtooltips.desc", "geyser.command.tooltips")); + registerBuiltInCommand(new ConnectionTestCommand(geyser, "connectiontest", "geyser.commands.connectiontest.desc", "geyser.command.connectiontest")); + if (this.geyser.getPlatformType() == PlatformType.STANDALONE) { + registerBuiltInCommand(new StopCommand(geyser, "stop", "geyser.commands.stop.desc", "geyser.command.stop")); + } + + if (!this.geyser.extensionManager().extensions().isEmpty()) { + registerBuiltInCommand(new ExtensionsCommand(this.geyser, "extensions", "geyser.commands.extensions.desc", "geyser.command.extensions")); + } + + GeyserDefineCommandsEvent defineCommandsEvent = new GeyserDefineCommandsEventImpl(this.commands) { + + @Override + public void register(@NonNull Command command) { + if (!(command instanceof GeyserExtensionCommand extensionCommand)) { + throw new IllegalArgumentException("Expected GeyserExtensionCommand as part of command registration but got " + command + "! Did you use the Command builder properly?"); + } + + registerExtensionCommand(extensionCommand.extension(), extensionCommand); + } + }; + this.geyser.eventBus().fire(defineCommandsEvent); + + // Stuff that needs to be done on a per-extension basis + for (Map.Entry> entry : this.extensionCommands.entrySet()) { + Extension extension = entry.getKey(); + + // Register this extension's root command + extensionRootCommands.put(extension.rootCommand(), extension); + + // Register help commands for all extensions with commands + String id = extension.description().id(); + HelpCommand extensionHelp = new HelpCommand( + extension.rootCommand(), + "help", + "geyser.commands.exthelp.desc", + "geyser.command.exthelp." + id, + entry.getValue()); // commands it provides help for + + registerExtensionCommand(extension, extensionHelp); + buildRootCommand("geyser.extension." + id + ".command", extensionHelp); + } + + // Wait for the right moment (depends on the platform) to register permissions. + geyser.eventBus().subscribe(this, GeyserRegisterPermissionsEvent.class, this::onRegisterPermissions); + } + + /** + * @return an immutable view of the root commands registered to this command registry + */ + @NonNull + public Collection rootCommands() { + return cloud.rootCommands(); + } + + /** + * For internal Geyser commands + */ + private void registerBuiltInCommand(GeyserCommand command) { + register(command, this.commands); + } + + private void registerExtensionCommand(@NonNull Extension extension, @NonNull GeyserCommand command) { + register(command, this.extensionCommands.computeIfAbsent(extension, e -> new HashMap<>())); + } + + protected void register(GeyserCommand command, Map commands) { + String root = command.rootCommand(); + String name = command.name(); + if (commands.containsKey(name)) { + throw new IllegalArgumentException("Command with root=%s, name=%s already registered".formatted(root, name)); + } + + command.register(cloud); + commands.put(name, command); + geyser.getLogger().debug(GeyserLocale.getLocaleStringLog("geyser.commands.registered", root + " " + name)); + + for (String alias : command.aliases()) { + commands.put(alias, command); + } + + String permission = command.permission(); + TriState defaultValue = command.permissionDefault(); + if (!permission.isBlank() && defaultValue != null) { + + TriState existingDefault = permissionDefaults.get(permission); + // Extensions might be using the same permission for two different commands + if (existingDefault != null && existingDefault != defaultValue) { + geyser.getLogger().debug("Overriding permission default %s:%s with %s".formatted(permission, existingDefault, defaultValue)); + } + + permissionDefaults.put(permission, defaultValue); + } + } + + /** + * Registers a root command to cloud that delegates to the given help command. + * The name of this root command is the root of the given help command. + * + * @param permission the permission of the root command. currently, it may or may not be + * applied depending on the platform. see below. + * @param help the help command to delegate to + */ + private void buildRootCommand(String permission, HelpCommand help) { + Builder builder = cloud.commandBuilder(help.rootCommand()); + + if (applyRootPermission) { + builder = builder.permission(permission); + permissionDefaults.put(permission, TriState.TRUE); + } + + cloud.command(builder.handler(context -> { + GeyserCommandSource source = context.sender(); + if (!source.hasPermission(help.permission())) { + // delegate if possible - otherwise we have nothing else to offer the user. + source.sendLocaleString(ExceptionHandlers.PERMISSION_FAIL_LANG_KEY); + return; + } + help.execute(source); + })); + } + + protected void onRegisterPermissions(GeyserRegisterPermissionsEvent event) { + for (Map.Entry permission : permissionDefaults.entrySet()) { + event.register(permission.getKey(), permission.getValue()); + } + } + + public boolean hasPermission(GeyserCommandSource source, String permission) { + // Handle blank permissions ourselves, as cloud only handles empty ones + return permission.isBlank() || cloud.hasPermission(source, permission); + } + + /** + * Returns the description of the given command + * + * @param command the root command node + * @param locale the ideal locale that the description should be in + * @return a description if found, otherwise an empty string. The locale is not guaranteed. + */ + @NonNull + public String description(@NonNull String command, @NonNull String locale) { + if (command.equals(DEFAULT_ROOT_COMMAND)) { + return GeyserLocale.getPlayerLocaleString("geyser.command.root.geyser", locale); + } + + Extension extension = extensionRootCommands.get(command); + if (extension != null) { + return GeyserLocale.getPlayerLocaleString("geyser.command.root.extension", locale, extension.name()); + } + return ""; + } + + /** + * Dispatches a command into cloud and handles any thrown exceptions. + * This method may or may not be blocking, depending on the {@link ExecutionCoordinator} in use by cloud. + */ + public void runCommand(@NonNull GeyserCommandSource source, @NonNull String command) { + cloud.commandExecutor().executeCommand(source, command); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/command/CommandSourceConverter.java b/core/src/main/java/org/geysermc/geyser/command/CommandSourceConverter.java new file mode 100644 index 000000000..1fa5871e0 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/command/CommandSourceConverter.java @@ -0,0 +1,113 @@ +/* + * 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.command; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.GeyserLogger; +import org.geysermc.geyser.session.GeyserSession; +import org.incendo.cloud.SenderMapper; + +import java.util.UUID; +import java.util.function.Function; +import java.util.function.Supplier; + +/** + * Converts {@link GeyserCommandSource}s to the server's command sender type (and back) in a lenient manner. + * + * @param senderType class of the server command sender type + * @param playerLookup function for looking up a player command sender by UUID + * @param consoleProvider supplier of the console command sender + * @param commandSourceLookup supplier of the platform implementation of the {@link GeyserCommandSource} + * @param server command sender type + */ +public record CommandSourceConverter(Class senderType, + Function playerLookup, + Supplier consoleProvider, + Function commandSourceLookup +) implements SenderMapper { + + /** + * Creates a new CommandSourceConverter for a server platform + * in which the player type is not a command sender type, and must be mapped. + * + * @param senderType class of the command sender type + * @param playerLookup function for looking up a player by UUID + * @param senderLookup function for converting a player to a command sender + * @param consoleProvider supplier of the console command sender + * @param commandSourceLookup supplier of the platform implementation of {@link GeyserCommandSource} + * @return a new CommandSourceConverter + * @param

    server player type + * @param server command sender type + */ + public static CommandSourceConverter layered(Class senderType, + Function playerLookup, + Function senderLookup, + Supplier consoleProvider, + Function commandSourceLookup) { + Function lookup = uuid -> { + P player = playerLookup.apply(uuid); + if (player == null) { + return null; + } + return senderLookup.apply(player); + }; + return new CommandSourceConverter<>(senderType, lookup, consoleProvider, commandSourceLookup); + } + + @Override + public @NonNull GeyserCommandSource map(@NonNull S base) { + return commandSourceLookup.apply(base); + } + + @Override + public @NonNull S reverse(GeyserCommandSource source) throws IllegalArgumentException { + Object handle = source.handle(); + if (senderType.isInstance(handle)) { + return senderType.cast(handle); // one of the server platform implementations + } + + if (source.isConsole()) { + return consoleProvider.get(); // one of the loggers + } + + if (!(source instanceof GeyserSession)) { + GeyserLogger logger = GeyserImpl.getInstance().getLogger(); + if (logger.isDebug()) { + logger.debug("Falling back to UUID for command sender lookup for a command source that is not a GeyserSession: " + source); + Thread.dumpStack(); + } + } + + // Ideally lookup should only be necessary for GeyserSession + UUID uuid = source.playerUuid(); + if (uuid != null) { + return playerLookup.apply(uuid); + } + + throw new IllegalArgumentException("failed to find sender for name=%s, uuid=%s".formatted(source.name(), source.playerUuid())); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/command/ExceptionHandlers.java b/core/src/main/java/org/geysermc/geyser/command/ExceptionHandlers.java new file mode 100644 index 000000000..45657a596 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/command/ExceptionHandlers.java @@ -0,0 +1,129 @@ +/* + * 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.command; + +import io.leangen.geantyref.GenericTypeReflector; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.GeyserLogger; +import org.geysermc.geyser.text.ChatColor; +import org.geysermc.geyser.text.GeyserLocale; +import org.geysermc.geyser.text.MinecraftLocale; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.exception.ArgumentParseException; +import org.incendo.cloud.exception.CommandExecutionException; +import org.incendo.cloud.exception.InvalidCommandSenderException; +import org.incendo.cloud.exception.InvalidSyntaxException; +import org.incendo.cloud.exception.NoPermissionException; +import org.incendo.cloud.exception.NoSuchCommandException; +import org.incendo.cloud.exception.handling.ExceptionController; + +import java.lang.reflect.Type; +import java.util.function.BiConsumer; + +/** + * Geyser's exception handlers for command execution with Cloud. + * Overrides Cloud's defaults so that messages can be customized to our liking: localization, etc. + */ +final class ExceptionHandlers { + + final static String PERMISSION_FAIL_LANG_KEY = "geyser.command.permission_fail"; + + private final ExceptionController controller; + + private ExceptionHandlers(ExceptionController controller) { + this.controller = controller; + } + + /** + * Clears the existing handlers that are registered to the given command manager, and repopulates them. + * + * @param manager the manager whose exception handlers will be modified + */ + static void register(CommandManager manager) { + new ExceptionHandlers(manager.exceptionController()).register(); + } + + private void register() { + // Yeet the default exception handlers that cloud provides so that we can perform localization. + controller.clearHandlers(); + + registerExceptionHandler(InvalidSyntaxException.class, + (src, e) -> src.sendLocaleString("geyser.command.invalid_syntax", e.correctSyntax())); + + registerExceptionHandler(InvalidCommandSenderException.class, (src, e) -> { + // We currently don't use cloud sender type requirements anywhere. + // This can be implemented better in the future if necessary. + Type type = e.requiredSenderTypes().iterator().next(); // just grab the first + String typeString = GenericTypeReflector.getTypeName(type); + src.sendLocaleString("geyser.command.invalid_sender", e.commandSender().getClass().getSimpleName(), typeString); + }); + + registerExceptionHandler(NoPermissionException.class, ExceptionHandlers::handleNoPermission); + + registerExceptionHandler(NoSuchCommandException.class, + (src, e) -> src.sendLocaleString("geyser.command.not_found")); + + registerExceptionHandler(ArgumentParseException.class, + (src, e) -> src.sendLocaleString("geyser.command.invalid_argument", e.getCause().getMessage())); + + registerExceptionHandler(CommandExecutionException.class, + (src, e) -> handleUnexpectedThrowable(src, e.getCause())); + + registerExceptionHandler(Throwable.class, + (src, e) -> handleUnexpectedThrowable(src, e.getCause())); + } + + private void registerExceptionHandler(Class type, BiConsumer handler) { + controller.registerHandler(type, context -> handler.accept(context.context().sender(), context.exception())); + } + + private static void handleNoPermission(GeyserCommandSource source, NoPermissionException exception) { + // custom handling if the source can't use the command because of additional requirements + if (exception.permissionResult() instanceof GeyserPermission.Result result) { + if (result.meta() == GeyserPermission.Result.Meta.NOT_BEDROCK) { + source.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.command.bedrock_only", source.locale())); + return; + } + if (result.meta() == GeyserPermission.Result.Meta.NOT_PLAYER) { + source.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.command.player_only", source.locale())); + return; + } + } else { + GeyserLogger logger = GeyserImpl.getInstance().getLogger(); + if (logger.isDebug()) { + logger.debug("Expected a GeyserPermission.Result for %s but instead got %s from %s".formatted(exception.currentChain(), exception.permissionResult(), exception.missingPermission())); + } + } + + // Result.NO_PERMISSION or generic permission failure + source.sendLocaleString(PERMISSION_FAIL_LANG_KEY); + } + + private static void handleUnexpectedThrowable(GeyserCommandSource source, Throwable throwable) { + source.sendMessage(MinecraftLocale.getLocaleString("command.failed", source.locale())); // java edition translation key + GeyserImpl.getInstance().getLogger().error("Exception while executing command handler", throwable); + } +} 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 47d57e73f..3cc05ca0c 100644 --- a/core/src/main/java/org/geysermc/geyser/command/GeyserCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/GeyserCommand.java @@ -25,65 +25,187 @@ package org.geysermc.geyser.command; -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 org.geysermc.geyser.api.event.lifecycle.GeyserRegisterPermissionsEvent; +import org.geysermc.geyser.api.util.TriState; +import org.geysermc.geyser.text.GeyserLocale; +import org.incendo.cloud.Command; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.context.CommandContext; +import org.incendo.cloud.description.CommandDescription; +import org.jetbrains.annotations.Contract; import java.util.Collections; import java.util.List; -@Accessors(fluent = true) -@Getter -@RequiredArgsConstructor -public abstract class GeyserCommand implements Command { +public abstract class GeyserCommand implements org.geysermc.geyser.api.command.Command { + public static final String DEFAULT_ROOT_COMMAND = "geyser"; + + /** + * The second literal of the command. Note: the first literal is {@link #rootCommand()}. + */ + @NonNull + private final String name; - protected final String name; /** * The description of the command - will attempt to be translated. */ - protected final String description; - protected final String permission; - - private List aliases = Collections.emptyList(); - - public abstract void execute(@Nullable GeyserSession session, GeyserCommandSource sender, String[] args); + @NonNull + private final String description; /** - * If false, hides the command from being shown on the Geyser Standalone GUI. - * - * @return true if the command can be run on the server console - */ - @Override - public boolean isExecutableOnConsole() { - return true; - } - - /** - * Used in the GUI to know what subcommands can be run - * - * @return a list of all possible subcommands, or empty if none. + * The permission node required to run the command, or blank if not required. */ @NonNull - @Override - public List subCommands() { - return Collections.emptyList(); + private final String permission; + + /** + * The default value of the permission node. + * A null value indicates that the permission node should not be registered whatsoever. + * See {@link GeyserRegisterPermissionsEvent#register(String, TriState)} for TriState meanings. + */ + @Nullable + private final TriState permissionDefault; + + /** + * True if this command can be executed by players + */ + private final boolean playerOnly; + + /** + * True if this command can only be run by bedrock players + */ + private final boolean bedrockOnly; + + /** + * The aliases of the command {@link #name}. This should not be modified after construction. + */ + protected List aliases = Collections.emptyList(); + + public GeyserCommand(@NonNull String name, @NonNull String description, + @NonNull String permission, @Nullable TriState permissionDefault, + boolean playerOnly, boolean bedrockOnly) { + + if (name.isBlank()) { + throw new IllegalArgumentException("Command cannot be null or blank!"); + } + if (permission.isBlank()) { + // Cloud treats empty permissions as available to everyone, but not blank permissions. + // When registering commands, we must convert ALL whitespace permissions into empty ones, + // because we cannot override permission checks that Cloud itself performs + permission = ""; + permissionDefault = null; + } + + this.name = name; + this.description = description; + this.permission = permission; + this.permissionDefault = permissionDefault; + + if (bedrockOnly && !playerOnly) { + throw new IllegalArgumentException("Command cannot be bedrockOnly if it is not playerOnly"); + } + + this.playerOnly = playerOnly; + this.bedrockOnly = bedrockOnly; } - public void setAliases(List aliases) { - this.aliases = aliases; + public GeyserCommand(@NonNull String name, @NonNull String description, @NonNull String permission, @Nullable TriState permissionDefault) { + this(name, description, permission, permissionDefault, false, false); + } + + @NonNull + @Override + public final String name() { + return name; + } + + @NonNull + @Override + public final String description() { + return description; + } + + @NonNull + @Override + public final String permission() { + return permission; + } + + @Nullable + public final TriState permissionDefault() { + return permissionDefault; + } + + @Override + public final boolean isPlayerOnly() { + return playerOnly; + } + + @Override + public final boolean isBedrockOnly() { + return bedrockOnly; + } + + @NonNull + @Override + public final List aliases() { + return Collections.unmodifiableList(aliases); } /** - * Used for permission defaults on server implementations. - * - * @return if this command is designated to be used only by server operators. + * @return the first (literal) argument of this command, which comes before {@link #name()}. */ - @Override - public boolean isSuggestedOpOnly() { - return false; + public String rootCommand() { + return DEFAULT_ROOT_COMMAND; } -} \ No newline at end of file + + /** + * Returns a {@link org.incendo.cloud.permission.Permission} that handles {@link #isBedrockOnly()}, {@link #isPlayerOnly()}, and {@link #permission()}. + * + * @param manager the manager to be used for permission node checking + * @return a permission that will properly restrict usage of this command + */ + public final GeyserPermission commandPermission(CommandManager manager) { + return new GeyserPermission(bedrockOnly, playerOnly, permission, manager); + } + + /** + * Creates a new command builder with {@link #rootCommand()}, {@link #name()}, and {@link #aliases()} built on it. + * A permission predicate that takes into account {@link #permission()}, {@link #isBedrockOnly()}, and {@link #isPlayerOnly()} + * is applied. The Applicable from {@link #meta()} is also applied to the builder. + */ + @Contract(value = "_ -> new", pure = true) + public final Command.Builder baseBuilder(CommandManager manager) { + return manager.commandBuilder(rootCommand()) + .literal(name, aliases.toArray(new String[0])) + .permission(commandPermission(manager)) + .apply(meta()); + } + + /** + * @return an Applicable that applies this command's description + */ + protected Command.Builder.Applicable meta() { + return builder -> builder + .commandDescription(CommandDescription.commandDescription(GeyserLocale.getLocaleStringLog(description))); // used in cloud-bukkit impl + } + + /** + * Registers this command to the given command manager. + * This method may be overridden to register more than one command. + *

    + * The default implementation is that {@link #baseBuilder(CommandManager)} with {@link #execute(CommandContext)} + * applied as the handler is registered to the manager. + */ + public void register(CommandManager manager) { + manager.command(baseBuilder(manager).handler(this::execute)); + } + + /** + * Executes this command + * @param context the context with which this command should be executed + */ + public abstract void execute(CommandContext context); +} diff --git a/core/src/main/java/org/geysermc/geyser/command/GeyserCommandExecutor.java b/core/src/main/java/org/geysermc/geyser/command/GeyserCommandExecutor.java deleted file mode 100644 index 37d2ef4fb..000000000 --- a/core/src/main/java/org/geysermc/geyser/command/GeyserCommandExecutor.java +++ /dev/null @@ -1,98 +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.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 java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -/** - * Represents helper functions for listening to {@code /geyser} or {@code /geyserext} commands. - */ -@AllArgsConstructor -public class GeyserCommandExecutor { - - protected final GeyserImpl geyser; - private final Map commands; - - public GeyserCommand getCommand(String label) { - return (GeyserCommand) commands.get(label); - } - - @Nullable - public GeyserSession getGeyserSession(GeyserCommandSource sender) { - if (sender.isConsole()) { - return null; - } - - for (GeyserSession session : geyser.getSessionManager().getSessions().values()) { - if (sender.name().equals(session.getPlayerEntity().getUsername())) { - return session; - } - } - return null; - } - - /** - * Determine which subcommands to suggest in the tab complete for the main /geyser command by a given command sender. - * - * @param sender The command sender to receive the tab complete suggestions. - * If the command sender is a bedrock player, an empty list will be returned as bedrock players do not get command argument suggestions. - * If the command sender is not a bedrock player, bedrock commands will not be shown. - * If the command sender does not have the permission for a given command, the command will not be shown. - * @return A list of command names to include in the tab complete - */ - public List tabComplete(GeyserCommandSource sender) { - if (getGeyserSession(sender) != null) { - // Bedrock doesn't get tab completions or argument suggestions - return Collections.emptyList(); - } - - List availableCommands = new ArrayList<>(); - - // Only show commands they have permission to use - for (Map.Entry entry : commands.entrySet()) { - Command geyserCommand = entry.getValue(); - if (sender.hasPermission(geyserCommand.permission())) { - if (geyserCommand.isBedrockOnly()) { - // Don't show commands the JE player can't run - continue; - } - - availableCommands.add(entry.getKey()); - } - } - - return availableCommands; - } -} diff --git a/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java b/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java deleted file mode 100644 index 72ed22381..000000000 --- a/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java +++ /dev/null @@ -1,330 +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.command; - -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; -import org.geysermc.geyser.api.command.CommandExecutor; -import org.geysermc.geyser.api.command.CommandSource; -import org.geysermc.geyser.api.event.lifecycle.GeyserDefineCommandsEvent; -import org.geysermc.geyser.api.extension.Extension; -import org.geysermc.geyser.command.defaults.AdvancedTooltipsCommand; -import org.geysermc.geyser.command.defaults.AdvancementsCommand; -import org.geysermc.geyser.command.defaults.ConnectionTestCommand; -import org.geysermc.geyser.command.defaults.DumpCommand; -import org.geysermc.geyser.command.defaults.ExtensionsCommand; -import org.geysermc.geyser.command.defaults.HelpCommand; -import org.geysermc.geyser.command.defaults.ListCommand; -import org.geysermc.geyser.command.defaults.OffhandCommand; -import org.geysermc.geyser.command.defaults.ReloadCommand; -import org.geysermc.geyser.command.defaults.SettingsCommand; -import org.geysermc.geyser.command.defaults.StatisticsCommand; -import org.geysermc.geyser.command.defaults.StopCommand; -import org.geysermc.geyser.command.defaults.VersionCommand; -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 java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -@RequiredArgsConstructor -public class GeyserCommandManager { - - @Getter - private final Map commands = new Object2ObjectOpenHashMap<>(12); - private final Map> extensionCommands = new Object2ObjectOpenHashMap<>(0); - - private final GeyserImpl geyser; - - public void init() { - registerBuiltInCommand(new HelpCommand(geyser, "help", "geyser.commands.help.desc", "geyser.command.help", "geyser", this.commands)); - registerBuiltInCommand(new ListCommand(geyser, "list", "geyser.commands.list.desc", "geyser.command.list")); - registerBuiltInCommand(new ReloadCommand(geyser, "reload", "geyser.commands.reload.desc", "geyser.command.reload")); - registerBuiltInCommand(new OffhandCommand(geyser, "offhand", "geyser.commands.offhand.desc", "geyser.command.offhand")); - registerBuiltInCommand(new DumpCommand(geyser, "dump", "geyser.commands.dump.desc", "geyser.command.dump")); - registerBuiltInCommand(new VersionCommand(geyser, "version", "geyser.commands.version.desc", "geyser.command.version")); - registerBuiltInCommand(new SettingsCommand(geyser, "settings", "geyser.commands.settings.desc", "geyser.command.settings")); - registerBuiltInCommand(new StatisticsCommand(geyser, "statistics", "geyser.commands.statistics.desc", "geyser.command.statistics")); - registerBuiltInCommand(new AdvancementsCommand("advancements", "geyser.commands.advancements.desc", "geyser.command.advancements")); - registerBuiltInCommand(new AdvancedTooltipsCommand("tooltips", "geyser.commands.advancedtooltips.desc", "geyser.command.tooltips")); - registerBuiltInCommand(new ConnectionTestCommand(geyser, "connectiontest", "geyser.commands.connectiontest.desc", "geyser.command.connectiontest")); - if (this.geyser.getPlatformType() == PlatformType.STANDALONE) { - registerBuiltInCommand(new StopCommand(geyser, "stop", "geyser.commands.stop.desc", "geyser.command.stop")); - } - - if (!this.geyser.extensionManager().extensions().isEmpty()) { - registerBuiltInCommand(new ExtensionsCommand(this.geyser, "extensions", "geyser.commands.extensions.desc", "geyser.command.extensions")); - } - - GeyserDefineCommandsEvent defineCommandsEvent = new GeyserDefineCommandsEventImpl(this.commands) { - - @Override - public void register(@NonNull Command command) { - if (!(command instanceof GeyserExtensionCommand extensionCommand)) { - throw new IllegalArgumentException("Expected GeyserExtensionCommand as part of command registration but got " + command + "! Did you use the Command builder properly?"); - } - - registerExtensionCommand(extensionCommand.extension(), extensionCommand); - } - }; - - this.geyser.eventBus().fire(defineCommandsEvent); - - // Register help commands for all extensions with commands - for (Map.Entry> entry : this.extensionCommands.entrySet()) { - 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())); - } - } - - /** - * For internal Geyser commands - */ - public void registerBuiltInCommand(GeyserCommand command) { - register(command, this.commands); - } - - public void registerExtensionCommand(@NonNull Extension extension, @NonNull Command command) { - register(command, this.extensionCommands.computeIfAbsent(extension, e -> new HashMap<>())); - } - - private void register(Command command, Map commands) { - commands.put(command.name(), command); - geyser.getLogger().debug(GeyserLocale.getLocaleStringLog("geyser.commands.registered", command.name())); - - if (command.aliases().isEmpty()) { - return; - } - - for (String alias : command.aliases()) { - commands.put(alias, command); - } - } - - @NonNull - public Map commands() { - return Collections.unmodifiableMap(this.commands); - } - - @NonNull - public Map> extensionCommands() { - return Collections.unmodifiableMap(this.extensionCommands); - } - - public boolean runCommand(GeyserCommandSource sender, String command) { - Extension extension = null; - for (Extension loopedExtension : this.extensionCommands.keySet()) { - if (command.startsWith(loopedExtension.description().id() + " ")) { - extension = loopedExtension; - break; - } - } - - if (!command.startsWith("geyser ") && extension == null) { - return false; - } - - command = command.trim().replace(extension != null ? extension.description().id() + " " : "geyser ", ""); - String label; - String[] args; - - if (!command.contains(" ")) { - label = command.toLowerCase(Locale.ROOT); - args = new String[0]; - } else { - label = command.substring(0, command.indexOf(" ")).toLowerCase(Locale.ROOT); - String argLine = command.substring(command.indexOf(" ") + 1); - args = argLine.contains(" ") ? argLine.split(" ") : new String[] { argLine }; - } - - Command cmd = (extension != null ? this.extensionCommands.getOrDefault(extension, Collections.emptyMap()) : this.commands).get(label); - if (cmd == null) { - sender.sendMessage(GeyserLocale.getLocaleStringLog("geyser.commands.invalid")); - return false; - } - - if (cmd instanceof GeyserCommand) { - if (sender instanceof GeyserSession) { - ((GeyserCommand) cmd).execute((GeyserSession) sender, sender, args); - } else { - if (!cmd.isBedrockOnly()) { - ((GeyserCommand) cmd).execute(null, sender, args); - } else { - geyser.getLogger().error(GeyserLocale.getLocaleStringLog("geyser.bootstrap.command.bedrock_only")); - } - } - } - - return true; - } - - /** - * Returns the description of the given command - * - * @param command Command to get the description for - * @return Command description - */ - public String description(String command) { - return ""; - } - - @RequiredArgsConstructor - public static class CommandBuilder implements Command.Builder { - private final Extension extension; - private Class sourceType; - private String name; - private String description = ""; - private String permission = ""; - private List aliases; - private boolean suggestedOpOnly = false; - private boolean executableOnConsole = true; - private List subCommands; - private boolean bedrockOnly; - private CommandExecutor executor; - - @Override - public Command.Builder source(@NonNull Class sourceType) { - this.sourceType = sourceType; - return this; - } - - public CommandBuilder name(@NonNull String name) { - this.name = name; - return this; - } - - public CommandBuilder description(@NonNull String description) { - this.description = description; - return this; - } - - public CommandBuilder permission(@NonNull String permission) { - this.permission = permission; - return this; - } - - public CommandBuilder aliases(@NonNull List aliases) { - this.aliases = aliases; - return this; - } - - @Override - public Command.Builder suggestedOpOnly(boolean suggestedOpOnly) { - this.suggestedOpOnly = suggestedOpOnly; - return this; - } - - public CommandBuilder executableOnConsole(boolean executableOnConsole) { - this.executableOnConsole = executableOnConsole; - return this; - } - - public CommandBuilder subCommands(@NonNull List subCommands) { - this.subCommands = subCommands; - return this; - } - - public CommandBuilder bedrockOnly(boolean bedrockOnly) { - this.bedrockOnly = bedrockOnly; - return this; - } - - public CommandBuilder executor(@NonNull CommandExecutor executor) { - this.executor = executor; - return this; - } - - @NonNull - public GeyserExtensionCommand build() { - if (this.name == null || this.name.isBlank()) { - throw new IllegalArgumentException("Command cannot be null or blank!"); - } - - if (this.sourceType == null) { - throw new IllegalArgumentException("Source type was not defined for command " + this.name + " in extension " + this.extension.name()); - } - - return new GeyserExtensionCommand(this.extension, this.name, this.description, this.permission) { - - @SuppressWarnings("unchecked") - @Override - public void execute(@Nullable GeyserSession session, GeyserCommandSource sender, String[] args) { - Class sourceType = CommandBuilder.this.sourceType; - CommandExecutor executor = CommandBuilder.this.executor; - if (sourceType.isInstance(session)) { - executor.execute((T) session, this, args); - return; - } - - if (sourceType.isInstance(sender)) { - executor.execute((T) sender, this, args); - return; - } - - GeyserImpl.getInstance().getLogger().debug("Ignoring command " + this.name + " due to no suitable sender."); - } - - @NonNull - @Override - public List aliases() { - return CommandBuilder.this.aliases == null ? Collections.emptyList() : CommandBuilder.this.aliases; - } - - @Override - public boolean isSuggestedOpOnly() { - return CommandBuilder.this.suggestedOpOnly; - } - - @NonNull - @Override - public List subCommands() { - return CommandBuilder.this.subCommands == null ? Collections.emptyList() : CommandBuilder.this.subCommands; - } - - @Override - public boolean isBedrockOnly() { - return CommandBuilder.this.bedrockOnly; - } - - @Override - public boolean isExecutableOnConsole() { - return CommandBuilder.this.executableOnConsole; - } - }; - } - } -} diff --git a/core/src/main/java/org/geysermc/geyser/command/GeyserCommandSource.java b/core/src/main/java/org/geysermc/geyser/command/GeyserCommandSource.java index 88d148b11..c14767496 100644 --- a/core/src/main/java/org/geysermc/geyser/command/GeyserCommandSource.java +++ b/core/src/main/java/org/geysermc/geyser/command/GeyserCommandSource.java @@ -25,11 +25,16 @@ package org.geysermc.geyser.command; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.command.CommandSource; +import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import java.util.UUID; + /** * Implemented on top of any class that can send a command. * For example, it wraps around Spigot's CommandSender class. @@ -46,4 +51,29 @@ public interface GeyserCommandSource extends CommandSource { default void sendMessage(Component message) { sendMessage(LegacyComponentSerializer.legacySection().serialize(message)); } + + default void sendLocaleString(String key, Object... values) { + sendMessage(GeyserLocale.getPlayerLocaleString(key, locale(), values)); + } + + default void sendLocaleString(String key) { + sendMessage(GeyserLocale.getPlayerLocaleString(key, locale())); + } + + @Override + default @Nullable GeyserSession connection() { + UUID uuid = playerUuid(); + if (uuid == null) { + return null; + } + return GeyserImpl.getInstance().connectionByUuid(uuid); + } + + /** + * @return the underlying platform handle that this source represents. + * If such handle doesn't exist, this itself is returned. + */ + default Object handle() { + return this; + } } diff --git a/core/src/main/java/org/geysermc/geyser/command/GeyserPermission.java b/core/src/main/java/org/geysermc/geyser/command/GeyserPermission.java new file mode 100644 index 000000000..1ee677e97 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/command/GeyserPermission.java @@ -0,0 +1,136 @@ +/* + * 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.command; + +import lombok.AllArgsConstructor; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.key.CloudKey; +import org.incendo.cloud.permission.Permission; +import org.incendo.cloud.permission.PermissionResult; +import org.incendo.cloud.permission.PredicatePermission; + +import static org.geysermc.geyser.command.GeyserPermission.Result.Meta; + +@AllArgsConstructor +public class GeyserPermission implements PredicatePermission { + + /** + * True if this permission requires the command source to be a bedrock player + */ + private final boolean bedrockOnly; + + /** + * True if this permission requires the command source to be any player + */ + private final boolean playerOnly; + + /** + * The permission node that the command source must have + */ + private final String permission; + + /** + * The command manager to delegate permission checks to + */ + private final CommandManager manager; + + @Override + public @NonNull Result testPermission(@NonNull GeyserCommandSource source) { + if (bedrockOnly) { + if (source.connection() == null) { + return new Result(Meta.NOT_BEDROCK); + } + // connection is present -> it is a player -> playerOnly is irrelevant + } else if (playerOnly) { + if (source.isConsole()) { + return new Result(Meta.NOT_PLAYER); // must be a player but is console + } + } + + if (permission.isBlank() || manager.hasPermission(source, permission)) { + return new Result(Meta.ALLOWED); + } + return new Result(Meta.NO_PERMISSION); + } + + @Override + public @NonNull CloudKey key() { + return CloudKey.cloudKey(permission); + } + + /** + * Basic implementation of cloud's {@link PermissionResult} that delegates to the more informative {@link Meta}. + */ + public final class Result implements PermissionResult { + + private final Meta meta; + + private Result(Meta meta) { + this.meta = meta; + } + + public Meta meta() { + return meta; + } + + @Override + public boolean allowed() { + return meta == Meta.ALLOWED; + } + + @Override + public @NonNull Permission permission() { + return GeyserPermission.this; + } + + /** + * More detailed explanation of whether the permission check passed. + */ + public enum Meta { + + /** + * The source must be a bedrock player, but is not. + */ + NOT_BEDROCK, + + /** + * The source must be a player, but is not. + */ + NOT_PLAYER, + + /** + * The source does not have a required permission node. + */ + NO_PERMISSION, + + /** + * The source meets all requirements. + */ + ALLOWED + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/AdvancedTooltipsCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/AdvancedTooltipsCommand.java index 466515b3f..75b9252da 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/AdvancedTooltipsCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/AdvancedTooltipsCommand.java @@ -25,33 +25,32 @@ package org.geysermc.geyser.command.defaults; +import org.geysermc.geyser.api.util.TriState; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.MinecraftLocale; +import org.incendo.cloud.context.CommandContext; + +import java.util.Objects; public class AdvancedTooltipsCommand extends GeyserCommand { + public AdvancedTooltipsCommand(String name, String description, String permission) { - super(name, description, permission); + super(name, description, permission, TriState.TRUE, true, true); } @Override - public void execute(GeyserSession session, GeyserCommandSource sender, String[] args) { - if (session != null) { - String onOrOff = session.isAdvancedTooltips() ? "off" : "on"; - session.setAdvancedTooltips(!session.isAdvancedTooltips()); - session.sendMessage("§l§e" + MinecraftLocale.getLocaleString("debug.prefix", session.locale()) + " §r" + MinecraftLocale.getLocaleString("debug.advanced_tooltips." + onOrOff, session.locale())); - session.getInventoryTranslator().updateInventory(session, session.getPlayerInventory()); - } - } + public void execute(CommandContext context) { + GeyserSession session = Objects.requireNonNull(context.sender().connection()); - @Override - public boolean isExecutableOnConsole() { - return false; - } - - @Override - public boolean isBedrockOnly() { - return true; + String onOrOff = session.isAdvancedTooltips() ? "off" : "on"; + session.setAdvancedTooltips(!session.isAdvancedTooltips()); + session.sendMessage(ChatColor.BOLD + ChatColor.YELLOW + + MinecraftLocale.getLocaleString("debug.prefix", session.locale()) + + " " + ChatColor.RESET + + MinecraftLocale.getLocaleString("debug.advanced_tooltips." + onOrOff, session.locale())); + session.getInventoryTranslator().updateInventory(session, session.getPlayerInventory()); } } diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/AdvancementsCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/AdvancementsCommand.java index 28253433f..0cba28f33 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/AdvancementsCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/AdvancementsCommand.java @@ -25,29 +25,23 @@ package org.geysermc.geyser.command.defaults; +import org.geysermc.geyser.api.util.TriState; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.session.GeyserSession; +import org.incendo.cloud.context.CommandContext; + +import java.util.Objects; public class AdvancementsCommand extends GeyserCommand { + public AdvancementsCommand(String name, String description, String permission) { - super(name, description, permission); + super(name, description, permission, TriState.TRUE, true, true); } @Override - public void execute(GeyserSession session, GeyserCommandSource sender, String[] args) { - if (session != null) { - session.getAdvancementsCache().buildAndShowMenuForm(); - } - } - - @Override - public boolean isExecutableOnConsole() { - return false; - } - - @Override - public boolean isBedrockOnly() { - return true; + public void execute(CommandContext context) { + GeyserSession session = Objects.requireNonNull(context.sender().connection()); + session.getAdvancementsCache().buildAndShowMenuForm(); } } 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 981c97595..d2066dba1 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,90 +26,82 @@ 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.api.util.TriState; 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; import org.geysermc.geyser.util.WebUtils; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.context.CommandContext; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.Random; import java.util.concurrent.CompletableFuture; +import static org.incendo.cloud.parser.standard.IntegerParser.integerParser; +import static org.incendo.cloud.parser.standard.StringParser.stringParser; + 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 static final String ADDRESS = "address"; + private static final String PORT = "port"; + private final GeyserImpl geyser; private final Random random = new Random(); public ConnectionTestCommand(GeyserImpl geyser, String name, String description, String permission) { - super(name, description, permission); + super(name, description, permission, TriState.NOT_SET); this.geyser = geyser; } @Override - public void execute(@Nullable GeyserSession session, GeyserCommandSource sender, String[] args) { - // Only allow the console to create dumps on Geyser Standalone - if (!sender.isConsole() && geyser.getPlatformType() == PlatformType.STANDALONE) { - sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.permission_fail", sender.locale())); - return; - } + public void register(CommandManager manager) { + manager.command(baseBuilder(manager) + .required(ADDRESS, stringParser()) + .optional(PORT, integerParser(0, 65535)) + .handler(this::execute)); + } - if (args.length == 0) { - sender.sendMessage("Provide the server IP and port you are trying to test Bedrock connections for. Example: `test.geysermc.org:19132`"); - return; - } + @Override + public void execute(CommandContext context) { + GeyserCommandSource source = context.sender(); + String ipArgument = context.get(ADDRESS); + Integer portArgument = context.getOrDefault(PORT, null); // null if port was not specified // 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 - int port; - if (fullAddress.length == 2) { - 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 = geyser.getConfig().getBedrock().broadcastPort(); - } - String ip = fullAddress[0]; + final String ip = ipArgument.replace("<", "").replace(">", ""); + final int port = portArgument != null ? portArgument : geyser.getConfig().getBedrock().broadcastPort(); // default bedrock port // 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."); + source.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."); + source.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."); + source.sendMessage("This tool checks if connections from other networks are possible, so you cannot check a local IP."); return; } // Issue: port out of bounds if (port <= 0 || port >= 65535) { - sender.sendMessage("The port you specified is invalid! Please specify a valid port."); + source.sendMessage("The port you specified is invalid! Please specify a valid port."); return; } @@ -118,37 +110,37 @@ public class ConnectionTestCommand extends GeyserCommand { // 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 (" + if (portArgument != null) { + source.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."); + source.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."); + source.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 \":\"), " + + source.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`."); + source.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 (" + source.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."); + source.sendMessage("You ONLY need to change the broadcast port if clients connects with a port different from the port Geyser is running on."); + source.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 (!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."); + source.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 (config.getBedrock().isEnableProxyProtocol()) { - sender.sendMessage("You have the `enable-proxy-protocol` setting enabled. " + + source.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."); } @@ -157,14 +149,14 @@ public class ConnectionTestCommand extends GeyserCommand { // Issue: SRV record? 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] + source.sendMessage("Bedrock Edition does not support SRV records. Try connecting to your server using the address " + record[3] + " and the port " + record[2] + ". If that fails, re-run this command with that address and port."); return; } // Issue: does Loopback need applying? if (LoopbackUtil.needsLoopback(GeyserImpl.getInstance().getLogger())) { - sender.sendMessage("Loopback is not applied on this computer! You will have issues connecting from the same computer. " + + source.sendMessage("Loopback is not applied on this computer! You will have issues connecting from the same computer. " + "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"); } @@ -178,7 +170,7 @@ public class ConnectionTestCommand extends GeyserCommand { String connectionTestMotd = "Geyser Connection Test " + randomStr; CONNECTION_TEST_MOTD = connectionTestMotd; - sender.sendMessage("Testing server connection to " + ip + " with port: " + port + " now. Please wait..."); + source.sendMessage("Testing server connection to " + ip + " with port: " + port + " now. Please wait..."); JsonNode output; try { String hostname = URLEncoder.encode(ip, StandardCharsets.UTF_8); @@ -200,31 +192,31 @@ public class ConnectionTestCommand extends GeyserCommand { 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 + "'). " + + source.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); + sendLinks(source); 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); + source.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(source); return; } - sender.sendMessage("Your server is likely online and working as of " + when + "!"); - sendLinks(sender); + source.sendMessage("Your server is likely online and working as of " + when + "!"); + sendLinks(source); return; } - sender.sendMessage("Your server is likely unreachable from outside the network!"); + source.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()); + source.sendMessage("Got the error message: " + message.asText()); } - sendLinks(sender); + sendLinks(source); } catch (Exception e) { - sender.sendMessage("An error occurred while trying to check your connection! Check the console for more information."); + source.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); } }); @@ -235,9 +227,4 @@ public class ConnectionTestCommand extends GeyserCommand { "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 - public boolean isSuggestedOpOnly() { - return true; - } } 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 b3fee375f..45100f525 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 @@ -29,43 +29,71 @@ import com.fasterxml.jackson.core.util.DefaultIndenter; 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.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.util.TriState; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.dump.DumpInfo; -import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.AsteriskSerializer; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.util.WebUtils; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.context.CommandContext; +import org.incendo.cloud.suggestion.SuggestionProvider; import java.io.FileOutputStream; import java.io.IOException; -import java.util.Arrays; +import java.util.ArrayList; import java.util.List; +import static org.incendo.cloud.parser.standard.StringArrayParser.stringArrayParser; + public class DumpCommand extends GeyserCommand { + private static final String ARGUMENTS = "args"; + private static final Iterable SUGGESTIONS = List.of("full", "offline", "logs"); + private final GeyserImpl geyser; private static final ObjectMapper MAPPER = new ObjectMapper(); private static final String DUMP_URL = "https://dump.geysermc.org/"; public DumpCommand(GeyserImpl geyser, String name, String description, String permission) { - super(name, description, permission); - + super(name, description, permission, TriState.NOT_SET); this.geyser = geyser; } - @Override - public void execute(GeyserSession session, GeyserCommandSource sender, String[] args) { - // Only allow the console to create dumps on Geyser Standalone - if (!sender.isConsole() && geyser.getPlatformType() == PlatformType.STANDALONE) { - sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.permission_fail", sender.locale())); - return; + @Override + public void register(CommandManager manager) { + manager.command(baseBuilder(manager) + .optional(ARGUMENTS, stringArrayParser(), SuggestionProvider.blockingStrings((ctx, input) -> { + // parse suggestions here + List inputs = new ArrayList<>(); + while (input.hasRemainingInput()) { + inputs.add(input.readStringSkipWhitespace()); + } + + if (inputs.size() <= 2) { + return SUGGESTIONS; // only `geyser dump` was typed (2 literals) + } + + // the rest of the input after `geyser dump` is for this argument + inputs = inputs.subList(2, inputs.size()); + + // don't suggest any words they have already typed + List suggestions = new ArrayList<>(); + SUGGESTIONS.forEach(suggestions::add); + suggestions.removeAll(inputs); + return suggestions; + })) + .handler(this::execute)); } + @Override + public void execute(CommandContext context) { + GeyserCommandSource source = context.sender(); + String[] args = context.getOrDefault(ARGUMENTS, new String[0]); + boolean showSensitive = false; boolean offlineDump = false; boolean addLog = false; @@ -75,13 +103,14 @@ public class DumpCommand extends GeyserCommand { case "full" -> showSensitive = true; case "offline" -> offlineDump = true; case "logs" -> addLog = true; + default -> context.sender().sendMessage("Invalid geyser dump option " + arg + "! Fallback to no arguments."); } } } AsteriskSerializer.showSensitive = showSensitive; - sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.dump.collecting", sender.locale())); + source.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.dump.collecting", source.locale())); String dumpData; try { if (offlineDump) { @@ -93,7 +122,7 @@ public class DumpCommand extends GeyserCommand { dumpData = MAPPER.writeValueAsString(new DumpInfo(addLog)); } } catch (IOException e) { - sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.commands.dump.collect_error", sender.locale())); + source.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.commands.dump.collect_error", source.locale())); geyser.getLogger().error(GeyserLocale.getLocaleStringLog("geyser.commands.dump.collect_error_short"), e); return; } @@ -101,21 +130,21 @@ public class DumpCommand extends GeyserCommand { String uploadedDumpUrl; if (offlineDump) { - sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.dump.writing", sender.locale())); + source.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.dump.writing", source.locale())); try { FileOutputStream outputStream = new FileOutputStream(GeyserImpl.getInstance().getBootstrap().getConfigFolder().resolve("dump.json").toFile()); outputStream.write(dumpData.getBytes()); outputStream.close(); } catch (IOException e) { - sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.commands.dump.write_error", sender.locale())); + source.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.commands.dump.write_error", source.locale())); geyser.getLogger().error(GeyserLocale.getLocaleStringLog("geyser.commands.dump.write_error_short"), e); return; } uploadedDumpUrl = "dump.json"; } else { - sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.dump.uploading", sender.locale())); + source.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.dump.uploading", source.locale())); String response; JsonNode responseNode; @@ -123,33 +152,22 @@ public class DumpCommand extends GeyserCommand { response = WebUtils.post(DUMP_URL + "documents", dumpData); responseNode = MAPPER.readTree(response); } catch (IOException e) { - sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.commands.dump.upload_error", sender.locale())); + source.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.commands.dump.upload_error", source.locale())); geyser.getLogger().error(GeyserLocale.getLocaleStringLog("geyser.commands.dump.upload_error_short"), e); return; } if (!responseNode.has("key")) { - sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.commands.dump.upload_error_short", sender.locale()) + ": " + (responseNode.has("message") ? responseNode.get("message").asText() : response)); + source.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.commands.dump.upload_error_short", source.locale()) + ": " + (responseNode.has("message") ? responseNode.get("message").asText() : response)); return; } uploadedDumpUrl = DUMP_URL + responseNode.get("key").asText(); } - sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.dump.message", sender.locale()) + " " + ChatColor.DARK_AQUA + uploadedDumpUrl); - if (!sender.isConsole()) { - geyser.getLogger().info(GeyserLocale.getLocaleStringLog("geyser.commands.dump.created", sender.name(), uploadedDumpUrl)); + source.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.dump.message", source.locale()) + " " + ChatColor.DARK_AQUA + uploadedDumpUrl); + if (!source.isConsole()) { + geyser.getLogger().info(GeyserLocale.getLocaleStringLog("geyser.commands.dump.created", source.name(), uploadedDumpUrl)); } } - - @NonNull - @Override - public List subCommands() { - return Arrays.asList("offline", "full", "logs"); - } - - @Override - public boolean isSuggestedOpOnly() { - return true; - } } 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 df33437d9..24881f2ca 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,14 +25,14 @@ 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.api.util.TriState; import org.geysermc.geyser.command.GeyserCommand; 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.incendo.cloud.context.CommandContext; import java.util.Comparator; import java.util.List; @@ -41,22 +41,23 @@ public class ExtensionsCommand extends GeyserCommand { private final GeyserImpl geyser; public ExtensionsCommand(GeyserImpl geyser, String name, String description, String permission) { - super(name, description, permission); - + super(name, description, permission, TriState.TRUE); this.geyser = geyser; } @Override - public void execute(@Nullable GeyserSession session, GeyserCommandSource sender, String[] args) { + public void execute(CommandContext context) { + GeyserCommandSource source = context.sender(); + // TODO: Pagination int page = 1; int maxPage = 1; - String header = GeyserLocale.getPlayerLocaleString("geyser.commands.extensions.header", sender.locale(), page, maxPage); - sender.sendMessage(header); + String header = GeyserLocale.getPlayerLocaleString("geyser.commands.extensions.header", source.locale(), page, maxPage); + source.sendMessage(header); this.geyser.extensionManager().extensions().stream().sorted(Comparator.comparing(Extension::name)).forEach(extension -> { String extensionName = (extension.isEnabled() ? ChatColor.GREEN : ChatColor.RED) + extension.name(); - sender.sendMessage("- " + extensionName + ChatColor.RESET + " v" + extension.description().version() + formatAuthors(extension.description().authors())); + source.sendMessage("- " + extensionName + ChatColor.RESET + " v" + extension.description().version() + formatAuthors(extension.description().authors())); }); } 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 c9671b089..9911863ab 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,61 +25,59 @@ package org.geysermc.geyser.command.defaults; -import org.geysermc.geyser.api.util.PlatformType; -import org.geysermc.geyser.GeyserImpl; +import com.google.common.base.Predicates; import org.geysermc.geyser.api.command.Command; +import org.geysermc.geyser.api.util.TriState; import org.geysermc.geyser.command.GeyserCommand; 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.incendo.cloud.context.CommandContext; +import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.Map; public class HelpCommand extends GeyserCommand { - private final GeyserImpl geyser; - private final String baseCommand; - private final Map commands; + private final String rootCommand; + private final Collection commands; - public HelpCommand(GeyserImpl geyser, String name, String description, String permission, - String baseCommand, Map commands) { - super(name, description, permission); - this.geyser = geyser; - this.baseCommand = baseCommand; - this.commands = commands; - - this.setAliases(Collections.singletonList("?")); + public HelpCommand(String rootCommand, String name, String description, String permission, Map commands) { + super(name, description, permission, TriState.TRUE); + this.rootCommand = rootCommand; + this.commands = commands.values(); + this.aliases = Collections.singletonList("?"); } - /** - * Sends the help menu to a command sender. Will not show certain commands depending on the command sender and session. - * - * @param session The Geyser session of the command sender, if it is a bedrock player. If null, bedrock-only commands will be hidden. - * @param sender The CommandSender to send the help message to. - * @param args Not used. - */ @Override - public void execute(GeyserSession session, GeyserCommandSource sender, String[] args) { + public String rootCommand() { + return rootCommand; + } + + @Override + public void execute(CommandContext context) { + execute(context.sender()); + } + + public void execute(GeyserCommandSource source) { + boolean bedrockPlayer = source.connection() != null; + + // todo: pagination int page = 1; int maxPage = 1; - 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); + String translationKey = this.rootCommand.equals(DEFAULT_ROOT_COMMAND) ? "geyser.commands.help.header" : "geyser.commands.extensions.header"; + String header = GeyserLocale.getPlayerLocaleString(translationKey, source.locale(), page, maxPage); + source.sendMessage(header); - this.commands.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(entry -> { - Command cmd = entry.getValue(); - - // Standalone hack-in since it doesn't have a concept of permissions - if (geyser.getPlatformType() == PlatformType.STANDALONE || sender.hasPermission(cmd.permission())) { - // Only list commands the player can actually run - if (cmd.isBedrockOnly() && session == null) { - return; - } - - sender.sendMessage(ChatColor.YELLOW + "/" + baseCommand + " " + entry.getKey() + ChatColor.WHITE + ": " + - GeyserLocale.getPlayerLocaleString(cmd.description(), sender.locale())); - } - }); + this.commands.stream() + .distinct() // remove aliases + .filter(bedrockPlayer ? Predicates.alwaysTrue() : cmd -> !cmd.isBedrockOnly()) // remove bedrock only commands if not a bedrock player + .filter(cmd -> source.hasPermission(cmd.permission())) + .sorted(Comparator.comparing(Command::name)) + .forEachOrdered(cmd -> { + String description = GeyserLocale.getPlayerLocaleString(cmd.description(), source.locale()); + source.sendMessage(ChatColor.YELLOW + "/" + rootCommand + " " + cmd.name() + ChatColor.WHITE + ": " + description); + }); } } diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/ListCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/ListCommand.java index 90446fbb6..5a76ab902 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/ListCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/ListCommand.java @@ -26,10 +26,12 @@ package org.geysermc.geyser.command.defaults; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.util.TriState; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; +import org.incendo.cloud.context.CommandContext; import java.util.stream.Collectors; @@ -38,22 +40,18 @@ public class ListCommand extends GeyserCommand { private final GeyserImpl geyser; public ListCommand(GeyserImpl geyser, String name, String description, String permission) { - super(name, description, permission); - + super(name, description, permission, TriState.NOT_SET); this.geyser = geyser; } @Override - public void execute(GeyserSession session, GeyserCommandSource sender, String[] args) { - String message = GeyserLocale.getPlayerLocaleString("geyser.commands.list.message", sender.locale(), - geyser.getSessionManager().size(), - geyser.getSessionManager().getAllSessions().stream().map(GeyserSession::bedrockUsername).collect(Collectors.joining(" "))); + public void execute(CommandContext context) { + GeyserCommandSource source = context.sender(); - sender.sendMessage(message); - } + String message = GeyserLocale.getPlayerLocaleString("geyser.commands.list.message", source.locale(), + geyser.getSessionManager().size(), + geyser.getSessionManager().getAllSessions().stream().map(GeyserSession::bedrockUsername).collect(Collectors.joining(" "))); - @Override - public boolean isSuggestedOpOnly() { - return true; + source.sendMessage(message); } } diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/OffhandCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/OffhandCommand.java index 6188e6924..5f9061618 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/OffhandCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/OffhandCommand.java @@ -25,33 +25,23 @@ package org.geysermc.geyser.command.defaults; -import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.util.TriState; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.session.GeyserSession; +import org.incendo.cloud.context.CommandContext; + +import java.util.Objects; public class OffhandCommand extends GeyserCommand { - public OffhandCommand(GeyserImpl geyser, String name, String description, String permission) { - super(name, description, permission); + public OffhandCommand(String name, String description, String permission) { + super(name, description, permission, TriState.TRUE, true, true); } @Override - public void execute(GeyserSession session, GeyserCommandSource sender, String[] args) { - if (session == null) { - return; - } - + public void execute(CommandContext context) { + GeyserSession session = Objects.requireNonNull(context.sender().connection()); session.requestOffhandSwap(); } - - @Override - public boolean isExecutableOnConsole() { - return false; - } - - @Override - public boolean isBedrockOnly() { - return true; - } } 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 987860238..e54b83ddf 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,12 +25,12 @@ package org.geysermc.geyser.command.defaults; -import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.util.TriState; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandSource; -import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; +import org.incendo.cloud.context.CommandContext; import java.util.concurrent.TimeUnit; @@ -39,27 +39,17 @@ public class ReloadCommand extends GeyserCommand { private final GeyserImpl geyser; public ReloadCommand(GeyserImpl geyser, String name, String description, String permission) { - super(name, description, permission); + super(name, description, permission, TriState.NOT_SET); this.geyser = geyser; } @Override - public void execute(GeyserSession session, GeyserCommandSource sender, String[] args) { - if (!sender.isConsole() && geyser.getPlatformType() == PlatformType.STANDALONE) { - return; - } - - String message = GeyserLocale.getPlayerLocaleString("geyser.commands.reload.message", sender.locale()); - - sender.sendMessage(message); + public void execute(CommandContext context) { + GeyserCommandSource source = context.sender(); + source.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.reload.message", source.locale())); 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::reloadGeyser, 10, TimeUnit.MILLISECONDS); } - - @Override - public boolean isSuggestedOpOnly() { - return true; - } } diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/SettingsCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/SettingsCommand.java index 7828cf1d2..a5734a69f 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/SettingsCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/SettingsCommand.java @@ -25,31 +25,24 @@ package org.geysermc.geyser.command.defaults; -import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.util.TriState; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.SettingsUtils; +import org.incendo.cloud.context.CommandContext; + +import java.util.Objects; public class SettingsCommand extends GeyserCommand { - public SettingsCommand(GeyserImpl geyser, String name, String description, String permission) { - super(name, description, permission); + + public SettingsCommand(String name, String description, String permission) { + super(name, description, permission, TriState.TRUE, true, true); } @Override - public void execute(GeyserSession session, GeyserCommandSource sender, String[] args) { - if (session != null) { - session.sendForm(SettingsUtils.buildForm(session)); - } - } - - @Override - public boolean isExecutableOnConsole() { - return false; - } - - @Override - public boolean isBedrockOnly() { - return true; + public void execute(CommandContext context) { + GeyserSession session = Objects.requireNonNull(context.sender().connection()); + session.sendForm(SettingsUtils.buildForm(session)); } } 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 5952ea00d..eebb9170c 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,35 +25,28 @@ package org.geysermc.geyser.command.defaults; -import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.util.TriState; 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; +import org.incendo.cloud.context.CommandContext; + +import java.util.Objects; public class StatisticsCommand extends GeyserCommand { - public StatisticsCommand(GeyserImpl geyser, String name, String description, String permission) { - super(name, description, permission); + public StatisticsCommand(String name, String description, String permission) { + super(name, description, permission, TriState.TRUE, true, true); } @Override - public void execute(GeyserSession session, GeyserCommandSource sender, String[] args) { - if (session == null) return; + public void execute(CommandContext context) { + GeyserSession session = Objects.requireNonNull(context.sender().connection()); session.setWaitingForStatistics(true); - ServerboundClientCommandPacket ServerboundClientCommandPacket = new ServerboundClientCommandPacket(ClientCommand.STATS); - session.sendDownstreamGamePacket(ServerboundClientCommandPacket); - } - - @Override - public boolean isExecutableOnConsole() { - return false; - } - - @Override - public boolean isBedrockOnly() { - return true; + ServerboundClientCommandPacket packet = new ServerboundClientCommandPacket(ClientCommand.STATS); + session.sendDownstreamGamePacket(packet); } } 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 1cd3050c9..f6dc1610a 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,12 +25,11 @@ package org.geysermc.geyser.command.defaults; -import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.util.TriState; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandSource; -import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.text.GeyserLocale; +import org.incendo.cloud.context.CommandContext; import java.util.Collections; @@ -39,24 +38,13 @@ public class StopCommand extends GeyserCommand { private final GeyserImpl geyser; public StopCommand(GeyserImpl geyser, String name, String description, String permission) { - super(name, description, permission); + super(name, description, permission, TriState.NOT_SET); this.geyser = geyser; - - this.setAliases(Collections.singletonList("shutdown")); + this.aliases = Collections.singletonList("shutdown"); } @Override - public void execute(GeyserSession session, GeyserCommandSource sender, String[] args) { - if (!sender.isConsole() && geyser.getPlatformType() == PlatformType.STANDALONE) { - sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.permission_fail", sender.locale())); - return; - } - + public void execute(CommandContext context) { geyser.getBootstrap().onGeyserShutdown(); } - - @Override - public boolean isSuggestedOpOnly() { - return true; - } } \ No newline at end of file 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 c6852d577..8d34c1bf0 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 @@ -29,13 +29,14 @@ import com.fasterxml.jackson.databind.JsonNode; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.util.PlatformType; +import org.geysermc.geyser.api.util.TriState; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.network.GameProtocol; -import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.util.WebUtils; +import org.incendo.cloud.context.CommandContext; import java.io.IOException; import java.util.List; @@ -45,13 +46,14 @@ public class VersionCommand extends GeyserCommand { private final GeyserImpl geyser; public VersionCommand(GeyserImpl geyser, String name, String description, String permission) { - super(name, description, permission); - + super(name, description, permission, TriState.NOT_SET); this.geyser = geyser; } @Override - public void execute(GeyserSession session, GeyserCommandSource sender, String[] args) { + public void execute(CommandContext context) { + GeyserCommandSource source = context.sender(); + String bedrockVersions; List supportedCodecs = GameProtocol.SUPPORTED_BEDROCK_CODECS; if (supportedCodecs.size() > 1) { @@ -67,45 +69,37 @@ public class VersionCommand extends GeyserCommand { javaVersions = supportedJavaVersions.get(0); } - sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.version.version", sender.locale(), + source.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.version.version", source.locale(), GeyserImpl.NAME, GeyserImpl.VERSION, javaVersions, bedrockVersions)); // Disable update checking in dev mode and for players in Geyser Standalone - if (!GeyserImpl.getInstance().isProductionEnvironment() || (!sender.isConsole() && geyser.getPlatformType() == PlatformType.STANDALONE)) { + if (!GeyserImpl.getInstance().isProductionEnvironment() || (!source.isConsole() && geyser.getPlatformType() == PlatformType.STANDALONE)) { return; } if (GeyserImpl.IS_DEV) { - // TODO cloud use language string - sender.sendMessage("You are running a development build of Geyser! Please report any bugs you find on our Discord server: %s" - .formatted("https://discord.gg/geysermc")); - //sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.core.dev_build", sender.locale(), "https://discord.gg/geysermc")); + source.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.core.dev_build", source.locale(), "https://discord.gg/geysermc")); return; } - sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.version.checking", sender.locale())); + source.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.version.checking", source.locale())); try { int buildNumber = this.geyser.buildNumber(); JsonNode response = WebUtils.getJson("https://download.geysermc.org/v2/projects/geyser/versions/latest/builds/latest"); int latestBuildNumber = response.get("build").asInt(); if (latestBuildNumber == buildNumber) { - sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.version.no_updates", sender.locale())); + source.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.version.no_updates", source.locale())); return; } - sender.sendMessage(GeyserLocale.getPlayerLocaleString( + source.sendMessage(GeyserLocale.getPlayerLocaleString( "geyser.commands.version.outdated", - sender.locale(), (latestBuildNumber - buildNumber), "https://geysermc.org/download" + source.locale(), (latestBuildNumber - buildNumber), "https://geysermc.org/download" )); } catch (IOException e) { GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.commands.version.failed"), e); - sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.commands.version.failed", sender.locale())); + source.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.commands.version.failed", source.locale())); } } - - @Override - public boolean isSuggestedOpOnly() { - return true; - } } diff --git a/core/src/main/java/org/geysermc/geyser/command/standalone/PermissionConfiguration.java b/core/src/main/java/org/geysermc/geyser/command/standalone/PermissionConfiguration.java new file mode 100644 index 000000000..edacd49ff --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/command/standalone/PermissionConfiguration.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.command.standalone; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; + +import java.util.Collections; +import java.util.Set; + +@Getter +@JsonIgnoreProperties(ignoreUnknown = true) +@SuppressWarnings("FieldMayBeFinal") // Jackson requires that the fields are not final +public class PermissionConfiguration { + + @JsonProperty("default-permissions") + private Set defaultPermissions = Collections.emptySet(); +} diff --git a/core/src/main/java/org/geysermc/geyser/command/standalone/StandaloneCloudCommandManager.java b/core/src/main/java/org/geysermc/geyser/command/standalone/StandaloneCloudCommandManager.java new file mode 100644 index 000000000..99c53f319 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/command/standalone/StandaloneCloudCommandManager.java @@ -0,0 +1,126 @@ +/* + * 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.command.standalone; + +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.event.lifecycle.GeyserRegisterPermissionCheckersEvent; +import org.geysermc.geyser.api.event.lifecycle.GeyserRegisterPermissionsEvent; +import org.geysermc.geyser.api.permission.PermissionChecker; +import org.geysermc.geyser.api.util.TriState; +import org.geysermc.geyser.command.CommandRegistry; +import org.geysermc.geyser.command.GeyserCommandSource; +import org.geysermc.geyser.util.FileUtils; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.execution.ExecutionCoordinator; +import org.incendo.cloud.internal.CommandRegistrationHandler; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +public class StandaloneCloudCommandManager extends CommandManager { + + private final GeyserImpl geyser; + + /** + * The checkers we use to test if a command source has a permission + */ + private final List permissionCheckers = new ArrayList<>(); + + /** + * Any permissions that all connections have + */ + private final Set basePermissions = new ObjectOpenHashSet<>(); + + public StandaloneCloudCommandManager(GeyserImpl geyser) { + super(ExecutionCoordinator.simpleCoordinator(), CommandRegistrationHandler.nullCommandRegistrationHandler()); + // simpleCoordinator: execute commands immediately on the calling thread. + // nullCommandRegistrationHandler: cloud is not responsible for handling our CommandRegistry, which is fairly decoupled. + this.geyser = geyser; + + // allow any extensions to customize permissions + geyser.getEventBus().fire((GeyserRegisterPermissionCheckersEvent) permissionCheckers::add); + + // must still implement a basic permission system + try { + File permissionsFile = geyser.getBootstrap().getConfigFolder().resolve("permissions.yml").toFile(); + FileUtils.fileOrCopiedFromResource(permissionsFile, "permissions.yml", geyser.getBootstrap()); + PermissionConfiguration config = FileUtils.loadConfig(permissionsFile, PermissionConfiguration.class); + basePermissions.addAll(config.getDefaultPermissions()); + } catch (Exception e) { + geyser.getLogger().error("Failed to load permissions.yml - proceeding without it", e); + } + } + + /** + * Fire a {@link GeyserRegisterPermissionsEvent} to determine any additions or removals to the base list of + * permissions. This should be called after any event listeners have been registered, such as that of {@link CommandRegistry}. + */ + public void fireRegisterPermissionsEvent() { + geyser.getEventBus().fire((GeyserRegisterPermissionsEvent) (permission, def) -> { + Objects.requireNonNull(permission, "permission"); + Objects.requireNonNull(def, "permission default for " + permission); + + if (permission.isBlank()) { + return; + } + if (def == TriState.TRUE) { + basePermissions.add(permission); + } + }); + } + + @Override + public boolean hasPermission(@NonNull GeyserCommandSource sender, @NonNull String permission) { + // Note: the two GeyserCommandSources on Geyser-Standalone are GeyserLogger and GeyserSession + // GeyserLogger#hasPermission always returns true + // GeyserSession#hasPermission delegates to this method, + // which is why this method doesn't just call GeyserCommandSource#hasPermission + if (sender.isConsole()) { + return true; + } + + // An empty or blank permission is treated as a lack of permission requirement + if (permission.isBlank()) { + return true; + } + + for (PermissionChecker checker : permissionCheckers) { + Boolean result = checker.hasPermission(sender, permission).toBoolean(); + if (result != null) { + return result; + } + // undefined - try the next checker to see if it has a defined value + } + // fallback to our list of default permissions + // note that a PermissionChecker may in fact override any values set here by returning FALSE + return basePermissions.contains(permission); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/event/type/GeyserDefineCommandsEventImpl.java b/core/src/main/java/org/geysermc/geyser/event/type/GeyserDefineCommandsEventImpl.java index e07a62d8a..4a6efbbd4 100644 --- a/core/src/main/java/org/geysermc/geyser/event/type/GeyserDefineCommandsEventImpl.java +++ b/core/src/main/java/org/geysermc/geyser/event/type/GeyserDefineCommandsEventImpl.java @@ -35,12 +35,12 @@ import java.util.Map; public abstract class GeyserDefineCommandsEventImpl implements GeyserDefineCommandsEvent { private final Map commands; - public GeyserDefineCommandsEventImpl(Map commands) { - this.commands = commands; + public GeyserDefineCommandsEventImpl(Map commands) { + this.commands = Collections.unmodifiableMap(commands); } @Override public @NonNull Map commands() { - return Collections.unmodifiableMap(this.commands); + return this.commands; } } diff --git a/core/src/main/java/org/geysermc/geyser/extension/command/GeyserExtensionCommand.java b/core/src/main/java/org/geysermc/geyser/extension/command/GeyserExtensionCommand.java index 4a7830c90..0b22a8b8e 100644 --- a/core/src/main/java/org/geysermc/geyser/extension/command/GeyserExtensionCommand.java +++ b/core/src/main/java/org/geysermc/geyser/extension/command/GeyserExtensionCommand.java @@ -25,19 +25,208 @@ package org.geysermc.geyser.extension.command; +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.api.command.CommandExecutor; +import org.geysermc.geyser.api.command.CommandSource; +import org.geysermc.geyser.api.connection.GeyserConnection; import org.geysermc.geyser.api.extension.Extension; +import org.geysermc.geyser.api.util.TriState; import org.geysermc.geyser.command.GeyserCommand; +import org.geysermc.geyser.command.GeyserCommandSource; +import org.geysermc.geyser.session.GeyserSession; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.context.CommandContext; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import static org.incendo.cloud.parser.standard.StringParser.greedyStringParser; public abstract class GeyserExtensionCommand extends GeyserCommand { + private final Extension extension; + private final String rootCommand; - public GeyserExtensionCommand(Extension extension, String name, String description, String permission) { - super(name, description, permission); + public GeyserExtensionCommand(@NonNull Extension extension, @NonNull String name, @NonNull String description, + @NonNull String permission, @Nullable TriState permissionDefault, + boolean playerOnly, boolean bedrockOnly) { + super(name, description, permission, permissionDefault, playerOnly, bedrockOnly); this.extension = extension; + this.rootCommand = Objects.requireNonNull(extension.rootCommand()); + + if (this.rootCommand.isBlank()) { + throw new IllegalStateException("rootCommand of extension " + extension.name() + " may not be blank"); + } } - public Extension extension() { + public final Extension extension() { return this.extension; } + + @Override + public final String rootCommand() { + return this.rootCommand; + } + + public static class Builder implements Command.Builder { + @NonNull private final Extension extension; + @Nullable private Class sourceType; + @Nullable private String name; + @NonNull private String description = ""; + @NonNull private String permission = ""; + @Nullable private TriState permissionDefault; + @Nullable private List aliases; + private boolean suggestedOpOnly = false; // deprecated for removal + private boolean playerOnly = false; + private boolean bedrockOnly = false; + @Nullable private CommandExecutor executor; + + public Builder(@NonNull Extension extension) { + this.extension = Objects.requireNonNull(extension); + } + + @Override + public Command.Builder source(@NonNull Class sourceType) { + this.sourceType = Objects.requireNonNull(sourceType, "command source type"); + return this; + } + + @Override + public Builder name(@NonNull String name) { + this.name = Objects.requireNonNull(name, "command name"); + return this; + } + + @Override + public Builder description(@NonNull String description) { + this.description = Objects.requireNonNull(description, "command description"); + return this; + } + + @Override + public Builder permission(@NonNull String permission) { + this.permission = Objects.requireNonNull(permission, "command permission"); + return this; + } + + @Override + public Builder permission(@NonNull String permission, @NonNull TriState defaultValue) { + this.permission = Objects.requireNonNull(permission, "command permission"); + this.permissionDefault = Objects.requireNonNull(defaultValue, "command permission defaultValue"); + return this; + } + + @Override + public Builder aliases(@NonNull List aliases) { + this.aliases = Objects.requireNonNull(aliases, "command aliases"); + return this; + } + + @SuppressWarnings("removal") // this is our doing + @Override + public Builder suggestedOpOnly(boolean suggestedOpOnly) { + this.suggestedOpOnly = suggestedOpOnly; + if (suggestedOpOnly) { + // the most amount of legacy/deprecated behaviour I'm willing to support + this.permissionDefault = TriState.NOT_SET; + } + return this; + } + + @SuppressWarnings("removal") // this is our doing + @Override + public Builder executableOnConsole(boolean executableOnConsole) { + this.playerOnly = !executableOnConsole; + return this; + } + + @Override + public Command.Builder playerOnly(boolean playerOnly) { + this.playerOnly = playerOnly; + return this; + } + + @Override + public Builder bedrockOnly(boolean bedrockOnly) { + this.bedrockOnly = bedrockOnly; + return this; + } + + @Override + public Builder executor(@NonNull CommandExecutor executor) { + this.executor = Objects.requireNonNull(executor, "command executor"); + return this; + } + + @NonNull + @Override + public GeyserExtensionCommand build() { + // These are captured in the anonymous lambda below and shouldn't change even if the builder does + final Class sourceType = this.sourceType; + final boolean suggestedOpOnly = this.suggestedOpOnly; + final CommandExecutor executor = this.executor; + + if (name == null) { + throw new IllegalArgumentException("name was not provided for a command in extension " + extension.name()); + } + if (sourceType == null) { + throw new IllegalArgumentException("Source type was not defined for command " + name + " in extension " + extension.name()); + } + if (executor == null) { + throw new IllegalArgumentException("Command executor was not defined for command " + name + " in extension " + extension.name()); + } + + // if the source type is a GeyserConnection then it is inherently bedrockOnly + final boolean bedrockOnly = this.bedrockOnly || GeyserConnection.class.isAssignableFrom(sourceType); + // a similar check would exist for executableOnConsole, but there is not a logger type exposed in the api + + GeyserExtensionCommand command = new GeyserExtensionCommand(extension, name, description, permission, permissionDefault, playerOnly, bedrockOnly) { + + @Override + public void register(CommandManager manager) { + manager.command(baseBuilder(manager) + .optional("args", greedyStringParser()) + .handler(this::execute)); + } + + @SuppressWarnings("unchecked") + @Override + public void execute(CommandContext context) { + GeyserCommandSource source = context.sender(); + String[] args = context.getOrDefault("args", "").split(" "); + + if (sourceType.isInstance(source)) { + executor.execute((T) source, this, args); + return; + } + + @Nullable GeyserSession session = source.connection(); + if (sourceType.isInstance(session)) { + executor.execute((T) session, this, args); + return; + } + + // currently, the only subclass of CommandSource exposed in the api is GeyserConnection. + // when this command was registered, we enabled bedrockOnly if the sourceType was a GeyserConnection. + // as a result, the permission checker should handle that case and this method shouldn't even be reached. + source.sendMessage("You must be a " + sourceType.getSimpleName() + " to run this command."); + } + + @SuppressWarnings("removal") // this is our doing + @Override + public boolean isSuggestedOpOnly() { + return suggestedOpOnly; + } + }; + + if (aliases != null) { + command.aliases = new ArrayList<>(aliases); + } + return command; + } + } } 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 9faa7424c..9cf2c0179 100644 --- a/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java +++ b/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java @@ -118,11 +118,6 @@ public class GeyserWorldManager extends WorldManager { return GameMode.SURVIVAL; } - @Override - public boolean hasPermission(GeyserSession session, String permission) { - return false; - } - @NonNull @Override public CompletableFuture<@Nullable DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addNbtData) { 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 4a20771f2..6baf9c2b4 100644 --- a/core/src/main/java/org/geysermc/geyser/level/WorldManager.java +++ b/core/src/main/java/org/geysermc/geyser/level/WorldManager.java @@ -185,15 +185,6 @@ public abstract class WorldManager { session.sendCommand("difficulty " + difficulty.name().toLowerCase(Locale.ROOT)); } - /** - * Checks if the given session's player has a permission - * - * @param session The session of the player to check the permission of - * @param permission The permission node to check - * @return True if the player has the requested permission, false if not - */ - public abstract boolean hasPermission(GeyserSession session, String permission); - /** * Returns a list of biome identifiers available on the server. */ 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 4b159438c..94de0c298 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 @@ -42,8 +42,8 @@ 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.extension.command.GeyserExtensionCommand; import org.geysermc.geyser.item.GeyserCustomItemData; import org.geysermc.geyser.item.GeyserCustomItemOptions; import org.geysermc.geyser.item.GeyserNonVanillaCustomItemData; @@ -67,7 +67,7 @@ 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(Command.Builder.class, args -> new GeyserExtensionCommand.Builder<>((Extension) args[0])); providers.put(CustomBlockComponents.Builder.class, args -> new GeyserCustomBlockComponents.Builder()); providers.put(CustomBlockData.Builder.class, args -> new GeyserCustomBlockData.Builder()); 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 97dd75905..899b53fb3 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -1454,11 +1454,28 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { return false; } + @Override + public UUID playerUuid() { + return javaUuid(); // CommandSource allows nullable + } + + @Override + public GeyserSession connection() { + return this; + } + @Override public String locale() { return clientData.getLanguageCode(); } + @Override + public boolean hasPermission(String permission) { + // for Geyser-Standalone, standalone's permission system will handle it. + // for server platforms, the session will be mapped to a server command sender, and the server's api will be used. + return geyser.commandRegistry().hasPermission(this, permission); + } + /** * Sends a chat message to the Java server. */ @@ -1771,17 +1788,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { upstream.sendPacket(gameRulesChangedPacket); } - /** - * Checks if the given session's player has a permission - * - * @param permission The permission node to check - * @return true if the player has the requested permission, false if not - */ - @Override - public boolean hasPermission(String permission) { - return geyser.getWorldManager().hasPermission(this, permission); - } - private static final Ability[] USED_ABILITIES = Ability.values(); /** 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 8d4df6f3f..1e84f032e 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 @@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.protocol.bedrock; import org.cloudburstmc.protocol.bedrock.packet.CommandRequestPacket; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.util.PlatformType; +import org.geysermc.geyser.command.CommandRegistry; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; @@ -43,13 +44,26 @@ public class BedrockCommandRequestTranslator extends PacketTranslator 0) { + String root = args[0]; + + CommandRegistry registry = GeyserImpl.getInstance().commandRegistry(); + if (registry.rootCommands().contains(root)) { + registry.runCommand(session, command); + return; // don't pass the command to the java server + } + } } + + if (MessageTranslator.isTooLong(command, session)) { + return; + } + + session.sendCommand(command); } } 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 aa815fab7..a7199be97 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 @@ -27,6 +27,7 @@ package org.geysermc.geyser.translator.protocol.bedrock.entity.player; import org.cloudburstmc.protocol.bedrock.packet.SetDefaultGameTypePacket; import org.cloudburstmc.protocol.bedrock.packet.SetPlayerGameTypePacket; +import org.geysermc.geyser.Permissions; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; @@ -41,7 +42,7 @@ public class BedrockSetDefaultGameTypeTranslator extends PacketTranslator= 2 && session.hasPermission("geyser.settings.server")) { + if (session.getOpPermissionLevel() >= 2 && session.hasPermission(Permissions.SERVER_SETTINGS)) { 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 176f00b8f..c3fa2a1b3 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,6 +25,7 @@ package org.geysermc.geyser.translator.protocol.bedrock.entity.player; +import org.geysermc.geyser.Permissions; import org.geysermc.mcprotocollib.protocol.data.game.setting.Difficulty; import org.cloudburstmc.protocol.bedrock.packet.SetDifficultyPacket; import org.geysermc.geyser.session.GeyserSession; @@ -39,7 +40,7 @@ public class BedrockSetDifficultyTranslator extends PacketTranslator= 2 && session.hasPermission("geyser.settings.server")) { + if (session.getOpPermissionLevel() >= 2 && session.hasPermission(Permissions.SERVER_SETTINGS)) { 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 f00156268..0590ca0ad 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 @@ -26,6 +26,7 @@ package org.geysermc.geyser.translator.protocol.bedrock.entity.player; import org.cloudburstmc.protocol.bedrock.packet.SetPlayerGameTypePacket; +import org.geysermc.geyser.Permissions; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; @@ -45,7 +46,7 @@ public class BedrockSetPlayerGameTypeTranslator extends PacketTranslator= 2 && session.hasPermission("geyser.settings.server")) { + if (session.getOpPermissionLevel() >= 2 && session.hasPermission(Permissions.SERVER_SETTINGS)) { 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 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 c0e3f5716..4c817ba01 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 @@ -41,7 +41,7 @@ import org.cloudburstmc.protocol.bedrock.data.command.*; import org.cloudburstmc.protocol.bedrock.packet.AvailableCommandsPacket; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.event.java.ServerDefineCommandsEvent; -import org.geysermc.geyser.command.GeyserCommandManager; +import org.geysermc.geyser.command.CommandRegistry; import org.geysermc.geyser.item.enchantment.Enchantment; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; @@ -122,7 +122,7 @@ public class JavaCommandsTranslator extends PacketTranslator commandData = new ArrayList<>(); IntSet commandNodes = new IntOpenHashSet(); @@ -151,8 +151,10 @@ public class JavaCommandsTranslator extends PacketTranslator new HashSet<>()).add(node.getName().toLowerCase()); + String name = node.getName().toLowerCase(Locale.ROOT); + String description = registry.description(name, session.locale()); + BedrockCommandInfo info = new BedrockCommandInfo(name, description, params); + commands.computeIfAbsent(info, $ -> new HashSet<>()).add(name); } var eventBus = session.getGeyser().eventBus(); 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 c8423c3be..87ed8af02 100644 --- a/core/src/main/java/org/geysermc/geyser/util/FileUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/FileUtils.java @@ -100,6 +100,18 @@ public class FileUtils { return file; } + /** + * Open the specified file or copy if from resources + * + * @param file File to open + * @param name Name of the resource get if needed + * @return File handle of the specified file + * @throws IOException if the file failed to copy from resource + */ + public static File fileOrCopiedFromResource(File file, String name, GeyserBootstrap bootstrap) throws IOException { + return fileOrCopiedFromResource(file, name, Function.identity(), bootstrap); + } + /** * Writes the given data to the specified file on disk * 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 6f46b191c..cb6ad6f0c 100644 --- a/core/src/main/java/org/geysermc/geyser/util/SettingsUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/SettingsUtils.java @@ -29,6 +29,7 @@ import org.cloudburstmc.protocol.bedrock.packet.SetDifficultyPacket; import org.geysermc.cumulus.component.DropdownComponent; import org.geysermc.cumulus.form.CustomForm; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.Permissions; import org.geysermc.geyser.level.GameRule; import org.geysermc.geyser.level.WorldManager; import org.geysermc.geyser.session.GeyserSession; @@ -81,7 +82,7 @@ public class SettingsUtils { } } - boolean showGamerules = session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.gamerules"); + boolean showGamerules = session.getOpPermissionLevel() >= 2 || session.hasPermission(Permissions.SETTINGS_GAMERULES); if (showGamerules) { builder.label("geyser.settings.title.game_rules") .translator(MinecraftLocale::getLocaleString); // we need translate gamerules next diff --git a/core/src/main/resources/languages b/core/src/main/resources/languages index afbf78bbe..60b20023a 160000 --- a/core/src/main/resources/languages +++ b/core/src/main/resources/languages @@ -1 +1 @@ -Subproject commit afbf78bbe0b39d0a076a42c228828c12f7f7da90 +Subproject commit 60b20023a92f084aba895ab0336e70fa7fb311fb diff --git a/core/src/main/resources/permissions.yml b/core/src/main/resources/permissions.yml new file mode 100644 index 000000000..4da9251e8 --- /dev/null +++ b/core/src/main/resources/permissions.yml @@ -0,0 +1,9 @@ + +# Add any permissions here that all players should have. +# Permissions for builtin Geyser commands do not have to be listed here. + +# If an extension/plugin registers their permissions with default values, entries here are typically unnecessary. +# If extensions don't register their permissions, permissions that everyone should have must be added here manually. + +default-permissions: + - geyser.command.help # this is unnecessary diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e50756ef1..f4abe18a9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -24,13 +24,15 @@ terminalconsoleappender = "1.2.0" folia = "1.19.4-R0.1-SNAPSHOT" viaversion = "4.9.2" adapters = "1.13-SNAPSHOT" +cloud = "2.0.0-rc.2" +cloud-minecraft = "2.0.0-beta.9" +cloud-minecraft-modded = "2.0.0-beta.7" commodore = "2.2" bungeecord = "a7c6ede" velocity = "3.3.0-SNAPSHOT" viaproxy = "3.2.1" fabric-loader = "0.15.11" fabric-api = "0.100.1+1.21" -fabric-permissions = "0.2-SNAPSHOT" neoforge-minecraft = "21.0.0-beta" mixin = "0.8.5" mixinextras = "0.3.5" @@ -86,8 +88,14 @@ jline-terminal = { group = "org.jline", name = "jline-terminal", version.ref = " jline-terminal-jna = { group = "org.jline", name = "jline-terminal-jna", version.ref = "jline" } jline-reader = { group = "org.jline", name = "jline-reader", version.ref = "jline" } +cloud-core = { group = "org.incendo", name = "cloud-core", version.ref = "cloud" } +cloud-paper = { group = "org.incendo", name = "cloud-paper", version.ref = "cloud-minecraft" } +cloud-velocity = { group = "org.incendo", name = "cloud-velocity", version.ref = "cloud-minecraft" } +cloud-bungee = { group = "org.incendo", name = "cloud-bungee", version.ref = "cloud-minecraft" } +cloud-fabric = { group = "org.incendo", name = "cloud-fabric", version.ref = "cloud-minecraft-modded" } +cloud-neoforge = { group = "org.incendo", name = "cloud-neoforge", version.ref = "cloud-minecraft-modded" } + folia-api = { group = "dev.folia", name = "folia-api", version.ref = "folia" } -paper-mojangapi = { group = "io.papermc.paper", name = "paper-mojangapi", version.ref = "folia" } mixin = { group = "org.spongepowered", name = "mixin", version.ref = "mixin" } mixinextras = { module = "io.github.llamalad7:mixinextras-common", version.ref = "mixinextras" } @@ -97,7 +105,6 @@ minecraft = { group = "com.mojang", name = "minecraft", version.ref = "minecraft # Check these on https://modmuss50.me/fabric.html 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" } From 48311f877106ec6cf61a208358eaf304f861436f Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 12 Jul 2024 20:42:31 +0200 Subject: [PATCH 188/233] Add a /geyser ping command (#4131) * Init: Add /geyser ping command * Block just console execution, not everything but console senders * Use RTT as that seems to vary less wildly compared to getPing() * Cleanup, use lang strings * Add ping() method to GeyserConnection in api * Update to cloud changes --- .../api/connection/GeyserConnection.java | 5 ++ .../geyser/command/CommandRegistry.java | 2 + .../geyser/command/defaults/PingCommand.java | 49 +++++++++++++++++++ .../geyser/session/GeyserSession.java | 8 +++ 4 files changed, 64 insertions(+) create mode 100644 core/src/main/java/org/geysermc/geyser/command/defaults/PingCommand.java 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 9bda4f903..ba559a462 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 @@ -132,4 +132,9 @@ public interface GeyserConnection extends Connection, CommandSource { @Deprecated @NonNull Set fogEffects(); + + /** + * Returns the current ping of the connection. + */ + int ping(); } diff --git a/core/src/main/java/org/geysermc/geyser/command/CommandRegistry.java b/core/src/main/java/org/geysermc/geyser/command/CommandRegistry.java index f07092afd..54681abea 100644 --- a/core/src/main/java/org/geysermc/geyser/command/CommandRegistry.java +++ b/core/src/main/java/org/geysermc/geyser/command/CommandRegistry.java @@ -43,6 +43,7 @@ import org.geysermc.geyser.command.defaults.ExtensionsCommand; import org.geysermc.geyser.command.defaults.HelpCommand; import org.geysermc.geyser.command.defaults.ListCommand; import org.geysermc.geyser.command.defaults.OffhandCommand; +import org.geysermc.geyser.command.defaults.PingCommand; import org.geysermc.geyser.command.defaults.ReloadCommand; import org.geysermc.geyser.command.defaults.SettingsCommand; import org.geysermc.geyser.command.defaults.StatisticsCommand; @@ -139,6 +140,7 @@ public class CommandRegistry implements EventRegistrar { registerBuiltInCommand(new AdvancementsCommand("advancements", "geyser.commands.advancements.desc", "geyser.command.advancements")); registerBuiltInCommand(new AdvancedTooltipsCommand("tooltips", "geyser.commands.advancedtooltips.desc", "geyser.command.tooltips")); registerBuiltInCommand(new ConnectionTestCommand(geyser, "connectiontest", "geyser.commands.connectiontest.desc", "geyser.command.connectiontest")); + registerBuiltInCommand(new PingCommand("ping", "geyser.commands.ping.desc", "geyser.command.ping")); if (this.geyser.getPlatformType() == PlatformType.STANDALONE) { registerBuiltInCommand(new StopCommand(geyser, "stop", "geyser.commands.stop.desc", "geyser.command.stop")); } diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/PingCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/PingCommand.java new file mode 100644 index 000000000..f39be0528 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/PingCommand.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.command.defaults; + +import org.geysermc.geyser.api.util.TriState; +import org.geysermc.geyser.command.GeyserCommand; +import org.geysermc.geyser.command.GeyserCommandSource; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.text.GeyserLocale; +import org.incendo.cloud.context.CommandContext; + +import java.util.Objects; + +public class PingCommand extends GeyserCommand { + + public PingCommand(String name, String description, String permission) { + super(name, description, permission, TriState.TRUE, true, true); + } + + @Override + public void execute(CommandContext context) { + GeyserSession session = Objects.requireNonNull(context.sender().connection()); + session.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.ping.message", session.locale(), session.ping())); + } +} + 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 899b53fb3..60321ea75 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -54,6 +54,8 @@ import org.cloudburstmc.math.vector.Vector3d; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.netty.channel.raknet.RakChildChannel; +import org.cloudburstmc.netty.handler.codec.raknet.common.RakSessionCodec; import org.cloudburstmc.protocol.bedrock.BedrockDisconnectReasons; import org.cloudburstmc.protocol.bedrock.BedrockServerSession; import org.cloudburstmc.protocol.bedrock.data.Ability; @@ -2098,6 +2100,12 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { return this.cameraData.fogEffects(); } + @Override + public int ping() { + RakSessionCodec rakSessionCodec = ((RakChildChannel) getUpstream().getSession().getPeer().getChannel()).rakPipeline().get(RakSessionCodec.class); + return (int) Math.floor(rakSessionCodec.getPing()); + } + public void addCommandEnum(String name, String enums) { softEnumPacket(name, SoftEnumUpdateType.ADD, enums); } From 813d1978875a6ef3538eb07e9767de9819959068 Mon Sep 17 00:00:00 2001 From: chris Date: Sun, 14 Jul 2024 22:09:55 +0200 Subject: [PATCH 189/233] Feature: API to switch items in the offhand/mainhand (#4819) --- .../java/org/geysermc/geyser/api/entity/EntityData.java | 6 ++++++ .../java/org/geysermc/geyser/entity/GeyserEntityData.java | 5 +++++ 2 files changed, 11 insertions(+) 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 index 90b3fc821..48c717089 100644 --- a/api/src/main/java/org/geysermc/geyser/api/entity/EntityData.java +++ b/api/src/main/java/org/geysermc/geyser/api/entity/EntityData.java @@ -81,4 +81,10 @@ public interface EntityData { * @return whether the movement is locked */ boolean isMovementLocked(); + + /** + * Sends a request to the Java server to switch the items in the main and offhand. + * There is no guarantee of the server accepting the request. + */ + void switchHands(); } diff --git a/core/src/main/java/org/geysermc/geyser/entity/GeyserEntityData.java b/core/src/main/java/org/geysermc/geyser/entity/GeyserEntityData.java index c9ef7a2dd..6f8f2525f 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/GeyserEntityData.java +++ b/core/src/main/java/org/geysermc/geyser/entity/GeyserEntityData.java @@ -96,4 +96,9 @@ public class GeyserEntityData implements EntityData { public boolean isMovementLocked() { return !movementLockOwners.isEmpty(); } + + @Override + public void switchHands() { + session.requestOffhandSwap(); + } } From 98c412c9edb4ab0e88ccb39a60272fbac7df05ae Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Tue, 23 Jul 2024 20:28:01 +0200 Subject: [PATCH 190/233] fix missing import --- core/src/main/java/org/geysermc/geyser/GeyserImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 464ebda96..01f1a118e 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -62,6 +62,7 @@ import org.geysermc.geyser.api.event.lifecycle.GeyserPostInitializeEvent; import org.geysermc.geyser.api.event.lifecycle.GeyserPostReloadEvent; import org.geysermc.geyser.api.event.lifecycle.GeyserPreInitializeEvent; import org.geysermc.geyser.api.event.lifecycle.GeyserPreReloadEvent; +import org.geysermc.geyser.api.event.lifecycle.GeyserRegisterPermissionsEvent; import org.geysermc.geyser.api.event.lifecycle.GeyserShutdownEvent; import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.api.network.BedrockListener; From 03187b6139214ed3a5d3e2697409d3ba9904127b Mon Sep 17 00:00:00 2001 From: rtm516 Date: Tue, 23 Jul 2024 19:43:19 +0100 Subject: [PATCH 191/233] Update DeviceOs to latest protocol (#4553) * Update DeviceOs to latest protocol * Revert enum name change and add deprecation annotations --- .../org/geysermc/floodgate/util/DeviceOs.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/common/src/main/java/org/geysermc/floodgate/util/DeviceOs.java b/common/src/main/java/org/geysermc/floodgate/util/DeviceOs.java index 406204759..1a92f9c40 100644 --- a/common/src/main/java/org/geysermc/floodgate/util/DeviceOs.java +++ b/common/src/main/java/org/geysermc/floodgate/util/DeviceOs.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 @@ -39,15 +39,19 @@ public enum DeviceOs { OSX("macOS"), AMAZON("Amazon"), GEARVR("Gear VR"), - HOLOLENS("Hololens"), + @Deprecated HOLOLENS("Hololens"), UWP("Windows"), WIN32("Windows x86"), DEDICATED("Dedicated"), - TVOS("Apple TV"), - PS4("PS4"), + @Deprecated TVOS("Apple TV"), + /** + * This is for all PlayStation platforms not just PS4 + */ + PS4("PlayStation"), NX("Switch"), - XBOX("Xbox One"), - WINDOWS_PHONE("Windows Phone"); + XBOX("Xbox"), + @Deprecated WINDOWS_PHONE("Windows Phone"), + LINUX("Linux"); private static final DeviceOs[] VALUES = values(); From f3ba5848c2b9fd187c4982bd449d894a837d469e Mon Sep 17 00:00:00 2001 From: chris Date: Thu, 1 Aug 2024 00:11:13 +0200 Subject: [PATCH 192/233] Extensions should specify geyser api version in the extension.yml (#3880) * let extensions specify geyser api version instead of base api version * fix spacing, @link formatting, properly check for compat * Proper warning, update to API changes to also check patch version * Bump base-api version * adapt to new base api changes * Actually bump to 2.4.1 * Update api/src/main/java/org/geysermc/geyser/api/extension/ExtensionDescription.java * Address reviews * Address reviews * Update to latest base api changes; proper extension *human* version checking * no need to apply a plugin, that's the default --------- Co-authored-by: Konicai <71294714+Konicai@users.noreply.github.com> --- api/build.gradle.kts | 18 ++++++- .../org.geysermc.geyser.api/BuildData.java | 53 +++++++++++++++++++ .../org/geysermc/geyser/api/GeyserApi.java | 11 ++++ .../api/extension/ExtensionDescription.java | 37 ++++++++----- .../extension/GeyserExtensionDescription.java | 10 ++-- .../extension/GeyserExtensionLoader.java | 40 +++++++++----- gradle.properties | 2 +- gradle/libs.versions.toml | 2 +- 8 files changed, 141 insertions(+), 32 deletions(-) create mode 100644 api/src/main/java-templates/org.geysermc.geyser.api/BuildData.java diff --git a/api/build.gradle.kts b/api/build.gradle.kts index bd54a9ce4..eac02ebeb 100644 --- a/api/build.gradle.kts +++ b/api/build.gradle.kts @@ -1,8 +1,24 @@ plugins { + // Allow blossom to mark sources root of templates + idea id("geyser.publish-conventions") + alias(libs.plugins.blossom) } dependencies { api(libs.base.api) api(libs.math) -} \ No newline at end of file +} + +version = property("version")!! +val apiVersion = (version as String).removeSuffix("-SNAPSHOT") + +sourceSets { + main { + blossom { + javaSources { + property("version", apiVersion) + } + } + } +} diff --git a/api/src/main/java-templates/org.geysermc.geyser.api/BuildData.java b/api/src/main/java-templates/org.geysermc.geyser.api/BuildData.java new file mode 100644 index 000000000..f9a580e7b --- /dev/null +++ b/api/src/main/java-templates/org.geysermc.geyser.api/BuildData.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 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; + +import org.geysermc.api.util.ApiVersion; + +/** + * Not a public API. For internal use only. May change without notice. + * This class is processed before compilation to insert build properties. + */ +class BuildData { + static final String VERSION = "{{ version }}"; + static final ApiVersion API_VERSION; + + static { + String[] parts = VERSION.split("\\."); + if (parts.length != 3) { + throw new RuntimeException("Invalid api version: " + VERSION); + } + + try { + int human = Integer.parseInt(parts[0]); + int major = Integer.parseInt(parts[1]); + int minor = Integer.parseInt(parts[2]); + API_VERSION = new ApiVersion(human, major, minor); + } catch (Exception e) { + throw new RuntimeException("Invalid api version: " + VERSION, e); + } + } +} 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 a9327d0db..5c20d06e1 100644 --- a/api/src/main/java/org/geysermc/geyser/api/GeyserApi.java +++ b/api/src/main/java/org/geysermc/geyser/api/GeyserApi.java @@ -29,6 +29,7 @@ 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.api.util.ApiVersion; import org.geysermc.geyser.api.command.CommandSource; import org.geysermc.geyser.api.connection.GeyserConnection; import org.geysermc.geyser.api.event.EventBus; @@ -169,4 +170,14 @@ public interface GeyserApi extends GeyserApiBase { static GeyserApi api() { return Geyser.api(GeyserApi.class); } + + /** + * Returns the {@link ApiVersion} representing the current Geyser api version. + * See the Geyser version outline) + * + * @return the current geyser api version + */ + default ApiVersion geyserApiVersion() { + return BuildData.API_VERSION; + } } diff --git a/api/src/main/java/org/geysermc/geyser/api/extension/ExtensionDescription.java b/api/src/main/java/org/geysermc/geyser/api/extension/ExtensionDescription.java index 2df3ee815..25daf450f 100644 --- a/api/src/main/java/org/geysermc/geyser/api/extension/ExtensionDescription.java +++ b/api/src/main/java/org/geysermc/geyser/api/extension/ExtensionDescription.java @@ -59,33 +59,46 @@ public interface ExtensionDescription { String main(); /** - * Gets the extension's major api version + * Represents the human api version that the extension requires. + * See the Geyser version outline) + * for more details on the Geyser API version. * - * @return the extension's major api version + * @return the extension's requested human api version + */ + int humanApiVersion(); + + /** + * Represents the major api version that the extension requires. + * See the Geyser version outline) + * for more details on the Geyser API version. + * + * @return the extension's requested major api version */ int majorApiVersion(); /** - * Gets the extension's minor api version + * Represents the minor api version that the extension requires. + * See the Geyser version outline) + * for more details on the Geyser API version. * - * @return the extension's minor api version + * @return the extension's requested minor api version */ int minorApiVersion(); /** - * Gets the extension's patch api version - * - * @return the extension's patch api version + * No longer in use. Geyser is now using an adaption of the romantic versioning scheme. + * See here for details. */ - int patchApiVersion(); + @Deprecated(forRemoval = true) + default int patchApiVersion() { + return minorApiVersion(); + } /** - * Gets the extension's api version. - * - * @return the extension's api version + * Returns the extension's requested Geyser Api version. */ default String apiVersion() { - return majorApiVersion() + "." + minorApiVersion() + "." + patchApiVersion(); + return humanApiVersion() + "." + majorApiVersion() + "." + minorApiVersion(); } /** 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 239ffc450..a84f12813 100644 --- a/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionDescription.java +++ b/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionDescription.java @@ -43,9 +43,9 @@ import java.util.regex.Pattern; public record GeyserExtensionDescription(@NonNull String id, @NonNull String name, @NonNull String main, + int humanApiVersion, int majorApiVersion, int minorApiVersion, - int patchApiVersion, @NonNull String version, @NonNull List authors) implements ExtensionDescription { @@ -82,9 +82,9 @@ public record GeyserExtensionDescription(@NonNull String id, throw new InvalidDescriptionException(GeyserLocale.getLocaleStringLog("geyser.extensions.load.failed_api_format", name, apiVersion)); } String[] api = apiVersion.split("\\."); - int majorApi = Integer.parseUnsignedInt(api[0]); - int minorApi = Integer.parseUnsignedInt(api[1]); - int patchApi = Integer.parseUnsignedInt(api[2]); + int humanApi = Integer.parseUnsignedInt(api[0]); + int majorApi = Integer.parseUnsignedInt(api[1]); + int minorApi = Integer.parseUnsignedInt(api[2]); List authors = new ArrayList<>(); if (source.author != null) { @@ -94,7 +94,7 @@ public record GeyserExtensionDescription(@NonNull String id, authors.addAll(source.authors); } - return new GeyserExtensionDescription(id, name, main, majorApi, minorApi, patchApi, version, authors); + return new GeyserExtensionDescription(id, name, main, humanApi, majorApi, minorApi, version, authors); } @NonNull 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 2f0ff1580..a56e00671 100644 --- a/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionLoader.java +++ b/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionLoader.java @@ -29,10 +29,15 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.RequiredArgsConstructor; import org.checkerframework.checker.nullness.qual.NonNull; -import org.geysermc.api.Geyser; +import org.geysermc.api.util.ApiVersion; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.GeyserApi; import org.geysermc.geyser.api.event.ExtensionEventBus; -import org.geysermc.geyser.api.extension.*; +import org.geysermc.geyser.api.extension.Extension; +import org.geysermc.geyser.api.extension.ExtensionDescription; +import org.geysermc.geyser.api.extension.ExtensionLoader; +import org.geysermc.geyser.api.extension.ExtensionLogger; +import org.geysermc.geyser.api.extension.ExtensionManager; import org.geysermc.geyser.api.extension.exception.InvalidDescriptionException; import org.geysermc.geyser.api.extension.exception.InvalidExtensionException; import org.geysermc.geyser.extension.event.GeyserExtensionEventBus; @@ -40,7 +45,12 @@ import org.geysermc.geyser.text.GeyserLocale; import java.io.IOException; import java.io.Reader; -import java.nio.file.*; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; @@ -176,16 +186,22 @@ public class GeyserExtensionLoader extends ExtensionLoader { 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; - } + // Check whether an extensions' requested api version is compatible + ApiVersion.Compatibility compatibility = GeyserApi.api().geyserApiVersion().supportsRequestedVersion( + description.humanApiVersion(), + description.majorApiVersion(), + description.minorApiVersion() + ); - // 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; + if (compatibility != ApiVersion.Compatibility.COMPATIBLE) { + // Workaround for the switch to the Geyser API version instead of the Base API version in extensions + if (compatibility == ApiVersion.Compatibility.HUMAN_DIFFER && description.humanApiVersion() == 1) { + GeyserImpl.getInstance().getLogger().warning("The extension %s requested the Base API version %s, which is deprecated in favor of specifying the Geyser API version. Please update the extension, or contact its developer." + .formatted(name, description.apiVersion())); + } else { + GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.extensions.load.failed_api_version", name, description.apiVersion())); + return; + } } GeyserExtensionContainer container = this.loadExtension(path, description); diff --git a/gradle.properties b/gradle.properties index a222b1d99..10d236a1b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,5 +7,5 @@ org.gradle.vfs.watch=false group=org.geysermc id=geyser -version=2.4.0-SNAPSHOT +version=2.4.1-SNAPSHOT description=Allows for players from Minecraft: Bedrock Edition to join Minecraft: Java Edition servers. diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f4abe18a9..b002c448c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -base-api = "1.0.0-SNAPSHOT" +base-api = "1.0.1-SNAPSHOT" cumulus = "1.1.2" erosion = "1.1-20240515.191456-1" events = "1.1-SNAPSHOT" From 8e3977810690e301772b6ac5083868cccf584483 Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Thu, 1 Aug 2024 00:59:28 +0200 Subject: [PATCH 193/233] Target 1.0.1 release of the base api --- 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 b002c448c..7a81ed923 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -base-api = "1.0.1-SNAPSHOT" +base-api = "1.0.1" cumulus = "1.1.2" erosion = "1.1-20240515.191456-1" events = "1.1-SNAPSHOT" From 5019b5aded85e9a938b27b3431fe551d9cbc8851 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Wed, 31 Jul 2024 19:22:56 -0500 Subject: [PATCH 194/233] Fix Geyser Api BuildData directory --- .../geysermc/geyser/api}/BuildData.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename api/src/main/java-templates/{org.geysermc.geyser.api => org/geysermc/geyser/api}/BuildData.java (100%) diff --git a/api/src/main/java-templates/org.geysermc.geyser.api/BuildData.java b/api/src/main/java-templates/org/geysermc/geyser/api/BuildData.java similarity index 100% rename from api/src/main/java-templates/org.geysermc.geyser.api/BuildData.java rename to api/src/main/java-templates/org/geysermc/geyser/api/BuildData.java From 95c6f7c9cf9779205588fee5f0f1f42080a83e41 Mon Sep 17 00:00:00 2001 From: Eclipse Date: Thu, 1 Aug 2024 01:18:49 +0000 Subject: [PATCH 195/233] Add advancement progress tracker (#4568) * Fix fetching advancements with invalid parents * Add progress tracker to advancements * Use Java language key for progress counter --- .../geyser/level/GeyserAdvancement.java | 12 ++-- .../session/cache/AdvancementsCache.java | 56 ++++++++++++++----- 2 files changed, 50 insertions(+), 18 deletions(-) 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 7d48b90af..7dad1639b 100644 --- a/core/src/main/java/org/geysermc/geyser/level/GeyserAdvancement.java +++ b/core/src/main/java/org/geysermc/geyser/level/GeyserAdvancement.java @@ -82,11 +82,15 @@ public class GeyserAdvancement { this.rootId = this.advancement.getId(); } else { // Go through our cache, and descend until we find the root ID - GeyserAdvancement advancement = advancementsCache.getStoredAdvancements().get(this.advancement.getParentId()); - if (advancement.getParentId() == null) { - this.rootId = advancement.getId(); + GeyserAdvancement parent = advancementsCache.getStoredAdvancements().get(this.advancement.getParentId()); + if (parent == null) { + // Parent doesn't exist, is invalid, or couldn't be found for another reason + // So assuming there is no parent and this is the root + this.rootId = this.advancement.getId(); + } else if (parent.getParentId() == null) { + this.rootId = parent.getId(); } else { - this.rootId = advancement.getRootId(advancementsCache); + this.rootId = parent.getRootId(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 be1eb3a5b..ac04bdf04 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 @@ -158,7 +158,15 @@ public class AdvancementsCache { // Cache language for easier access String language = session.locale(); - String earned = isEarned(advancement) ? "yes" : "no"; + boolean advancementHasProgress = advancement.getRequirements().size() > 1; + + int advancementProgress = getProgress(advancement); + int advancementRequirements = advancement.getRequirements().size(); + + boolean advancementEarned = advancementRequirements > 0 + && advancementProgress >= advancementRequirements; + + String earned = advancementEarned ? "yes" : "no"; String description = getColorFromAdvancementFrameType(advancement) + MessageTranslator.convertMessage(advancement.getDisplayData().getDescription(), language); String earnedString = GeyserLocale.getPlayerLocaleString("geyser.advancements.earned", language, MinecraftLocale.getLocaleString("gui." + earned, language)); @@ -171,10 +179,20 @@ public class AdvancementsCache { (Description) Mine stone with your new pickaxe Earned: Yes + Progress: 1/4 // When advancement has multiple requirements Parent Advancement: Minecraft // If relevant */ String content = description + "\n\n§f" + earnedString + "\n"; + + if (advancementHasProgress) { + // Only display progress with multiple requirements + String progress = MinecraftLocale.getLocaleString("advancements.progress", language) + .replaceFirst("%s", String.valueOf(advancementProgress)) + .replaceFirst("%s", String.valueOf(advancementRequirements)); + content += GeyserLocale.getPlayerLocaleString("geyser.advancements.progress", language, progress) + "\n"; + } + if (!currentAdvancementCategoryId.equals(advancement.getParentId())) { // Only display the parent if it is not the category content += GeyserLocale.getPlayerLocaleString("geyser.advancements.parentid", language, MessageTranslator.convertMessage(storedAdvancements.get(advancement.getParentId()).getDisplayData().getTitle(), language)); @@ -200,34 +218,44 @@ public class AdvancementsCache { * @return true if the advancement has been earned. */ public boolean isEarned(GeyserAdvancement advancement) { - boolean earned = false; - if (advancement.getRequirements().size() == 0) { + if (advancement.getRequirements().isEmpty()) { // Minecraft handles this case, so we better as well return false; } - Map progress = storedAdvancementProgress.get(advancement.getId()); - if (progress != null) { + // Progress should never be above requirements count, but you never know + return getProgress(advancement) >= advancement.getRequirements().size(); + } + + /** + * Determine the progress on an advancement. + * + * @param advancement the advancement to determine + * @return the progress on the advancement. + */ + public int getProgress(GeyserAdvancement advancement) { + if (advancement.getRequirements().isEmpty()) { + // Minecraft handles this case + return 0; + } + int progress = 0; + Map progressMap = storedAdvancementProgress.get(advancement.getId()); + if (progressMap != null) { // Each advancement's requirement must be fulfilled // For example, [[zombie, blaze, skeleton]] means that one of those three categories must be achieved // But [[zombie], [blaze], [skeleton]] means that all three requirements must be completed for (List requirements : advancement.getRequirements()) { - boolean requirementsDone = false; for (String requirement : requirements) { - Long obtained = progress.get(requirement); + Long obtained = progressMap.get(requirement); // -1 means that this particular component required for completing the advancement // has yet to be fulfilled if (obtained != null && !obtained.equals(-1L)) { - requirementsDone = true; - break; + progress++; } } - if (!requirementsDone) { - return false; - } } - earned = true; } - return earned; + + return progress; } public String getColorFromAdvancementFrameType(GeyserAdvancement advancement) { From 3d7e62a408b2b4a6f86430e940a0219c5b595fa0 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Thu, 1 Aug 2024 18:35:03 -0400 Subject: [PATCH 196/233] Fix some server switching issues and GeyserConnect --- .../type/player/SessionPlayerEntity.java | 2 +- .../geysermc/geyser/level/JavaDimension.java | 5 ++++- .../geyser/session/GeyserSession.java | 10 ++++++++- .../geyser/session/cache/ChunkCache.java | 14 ++---------- .../protocol/java/JavaLoginTranslator.java | 22 ++++++++----------- .../JavaHorseScreenOpenTranslator.java | 6 ++++- .../JavaLevelChunkWithLightTranslator.java | 4 ++-- .../org/geysermc/geyser/util/ChunkUtils.java | 6 ++--- .../geysermc/geyser/util/DimensionUtils.java | 2 +- .../geysermc/geyser/util/InventoryUtils.java | 2 +- 10 files changed, 37 insertions(+), 36 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 dc0545cee..b924461af 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 @@ -321,7 +321,7 @@ public class SessionPlayerEntity extends PlayerEntity { public int voidFloorPosition() { // The void floor is offset about 40 blocks below the bottom of the world - BedrockDimension bedrockDimension = session.getChunkCache().getBedrockDimension(); + BedrockDimension bedrockDimension = session.getBedrockDimension(); return bedrockDimension.minY() - 40; } 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 7462844fc..0ca428830 100644 --- a/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java +++ b/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java @@ -34,6 +34,9 @@ import org.geysermc.geyser.util.DimensionUtils; * Represents the information we store from the current Java dimension * @param piglinSafe Whether piglins and hoglins are safe from conversion in this dimension. * This controls if they have the shaking effect applied in the dimension. + * @param bedrockId the Bedrock dimension ID of this dimension. + * As a Java dimension can be null in some login cases (e.g. GeyserConnect), make sure the player + * is logged in before utilizing this field. */ public record JavaDimension(int minY, int maxY, boolean piglinSafe, double worldCoordinateScale, int bedrockId, boolean isNetherLike) { @@ -46,7 +49,7 @@ public record JavaDimension(int minY, int maxY, boolean piglinSafe, double world // Set if piglins/hoglins should shake boolean piglinSafe = dimension.getBoolean("piglin_safe"); // Load world coordinate scale for the world border - double coordinateScale = dimension.getDouble("coordinate_scale"); + double coordinateScale = dimension.getNumber("coordinate_scale").doubleValue(); // FIXME see if we can change this in the NBT library itself. boolean isNetherLike; // Cache the Bedrock version of this dimension, and base it off the ID - THE ID CAN CHANGE!!! 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 60321ea75..9a990865e 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -137,6 +137,7 @@ import org.geysermc.geyser.inventory.recipe.GeyserRecipe; import org.geysermc.geyser.inventory.recipe.GeyserStonecutterData; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.type.BlockItem; +import org.geysermc.geyser.level.BedrockDimension; import org.geysermc.geyser.level.JavaDimension; import org.geysermc.geyser.level.physics.CollisionManager; import org.geysermc.geyser.network.netty.LocalSession; @@ -386,6 +387,13 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @MonotonicNonNull @Setter private JavaDimension dimensionType = null; + /** + * Which dimension Bedrock understands themselves to be in. + * This should only be set after the ChangeDimensionPacket is sent, or + * right before the StartGamePacket is sent. + */ + @Setter + private BedrockDimension bedrockDimension = BedrockDimension.OVERWORLD; @Setter private int breakingBlock; @@ -1547,7 +1555,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { startGamePacket.setRotation(Vector2f.from(1, 1)); startGamePacket.setSeed(-1L); - startGamePacket.setDimensionId(DimensionUtils.javaToBedrock(chunkCache.getBedrockDimension())); + startGamePacket.setDimensionId(DimensionUtils.javaToBedrock(bedrockDimension)); startGamePacket.setGeneratorId(1); startGamePacket.setLevelGameType(GameType.SURVIVAL); startGamePacket.setDifficulty(1); 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 7b279857a..ad5237c23 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,17 +25,14 @@ package org.geysermc.geyser.session.cache; -import org.geysermc.geyser.level.block.type.Block; -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; import lombok.Setter; -import org.geysermc.geyser.level.BedrockDimension; -import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.level.chunk.GeyserChunk; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.MathUtils; +import org.geysermc.mcprotocollib.protocol.data.game.chunk.DataPalette; public class ChunkCache { private final boolean cache; @@ -46,13 +43,6 @@ public class ChunkCache { @Setter private int heightY; - /** - * Which dimension Bedrock understands themselves to be in. - */ - @Getter - @Setter - private BedrockDimension bedrockDimension = BedrockDimension.OVERWORLD; - public ChunkCache(GeyserSession session) { this.cache = !session.getGeyser().getWorldManager().hasOwnChunkCache(); // To prevent Spigot from initializing chunks = cache ? new Long2ObjectOpenHashMap<>() : null; 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 cf4b7058b..a6d6e6c70 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,14 +64,17 @@ public class JavaLoginTranslator extends PacketTranslator> 4) - 1; int sectionCount; @@ -509,7 +509,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator entry : session.getItemFrameCache().entrySet()) { 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 2e7df51bd..288b425ba 100644 --- a/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java @@ -149,7 +149,7 @@ public class ChunkUtils { } public static void sendEmptyChunk(GeyserSession session, int chunkX, int chunkZ, boolean forceUpdate) { - BedrockDimension bedrockDimension = session.getChunkCache().getBedrockDimension(); + BedrockDimension bedrockDimension = session.getBedrockDimension(); int bedrockSubChunkCount = bedrockDimension.height() >> 4; byte[] payload; @@ -167,7 +167,7 @@ public class ChunkUtils { byteBuf.readBytes(payload); LevelChunkPacket data = new LevelChunkPacket(); - data.setDimension(DimensionUtils.javaToBedrock(session.getChunkCache().getBedrockDimension())); + data.setDimension(DimensionUtils.javaToBedrock(session.getBedrockDimension())); data.setChunkX(chunkX); data.setChunkZ(chunkZ); data.setSubChunksLength(0); @@ -214,7 +214,7 @@ public class ChunkUtils { throw new RuntimeException("Maximum Y must be a multiple of 16!"); } - BedrockDimension bedrockDimension = session.getChunkCache().getBedrockDimension(); + BedrockDimension bedrockDimension = session.getBedrockDimension(); // Yell in the console if the world height is too height in the current scenario // The constraints change depending on if the player is in the overworld or not, and if experimental height is enabled // (Ignore this for the Nether. We can't change that at the moment without the workaround. :/ ) 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 821358bd8..f043631b6 100644 --- a/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java @@ -179,7 +179,7 @@ public class DimensionUtils { } public static void setBedrockDimension(GeyserSession session, int bedrockDimension) { - session.getChunkCache().setBedrockDimension(switch (bedrockDimension) { + session.setBedrockDimension(switch (bedrockDimension) { case BEDROCK_END_ID -> BedrockDimension.THE_END; case BEDROCK_DEFAULT_NETHER_ID -> BedrockDimension.THE_NETHER; // JavaDimension *should* be set to BEDROCK_END_ID if the Nether workaround is enabled. default -> BedrockDimension.OVERWORLD; 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 b0bfffc19..d8c41d626 100644 --- a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java @@ -159,7 +159,7 @@ public class InventoryUtils { @Nullable public static Vector3i findAvailableWorldSpace(GeyserSession session) { // Check if a fake block can be placed, either above the player or beneath. - BedrockDimension dimension = session.getChunkCache().getBedrockDimension(); + BedrockDimension dimension = session.getBedrockDimension(); int minY = dimension.minY(), maxY = minY + dimension.height(); Vector3i flatPlayerPosition = session.getPlayerEntity().getPosition().toInt(); Vector3i position = flatPlayerPosition.add(Vector3i.UP); From 61ae5debd4527875a5dc0bff912c029f2501a1b1 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Sat, 3 Aug 2024 10:23:06 -0500 Subject: [PATCH 197/233] Allow dumps to be created even if GeyserServer failed to start (#4930) --- .../geyser/command/defaults/DumpCommand.java | 50 ++++++++++--------- .../org/geysermc/geyser/dump/DumpInfo.java | 22 ++++---- 2 files changed, 39 insertions(+), 33 deletions(-) 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 45100f525..fc46f0108 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 @@ -63,31 +63,31 @@ public class DumpCommand extends GeyserCommand { this.geyser = geyser; } - @Override - public void register(CommandManager manager) { - manager.command(baseBuilder(manager) - .optional(ARGUMENTS, stringArrayParser(), SuggestionProvider.blockingStrings((ctx, input) -> { - // parse suggestions here - List inputs = new ArrayList<>(); - while (input.hasRemainingInput()) { - inputs.add(input.readStringSkipWhitespace()); - } + @Override + public void register(CommandManager manager) { + manager.command(baseBuilder(manager) + .optional(ARGUMENTS, stringArrayParser(), SuggestionProvider.blockingStrings((ctx, input) -> { + // parse suggestions here + List inputs = new ArrayList<>(); + while (input.hasRemainingInput()) { + inputs.add(input.readStringSkipWhitespace()); + } - if (inputs.size() <= 2) { - return SUGGESTIONS; // only `geyser dump` was typed (2 literals) - } + if (inputs.size() <= 2) { + return SUGGESTIONS; // only `geyser dump` was typed (2 literals) + } - // the rest of the input after `geyser dump` is for this argument - inputs = inputs.subList(2, inputs.size()); + // the rest of the input after `geyser dump` is for this argument + inputs = inputs.subList(2, inputs.size()); - // don't suggest any words they have already typed - List suggestions = new ArrayList<>(); - SUGGESTIONS.forEach(suggestions::add); - suggestions.removeAll(inputs); - return suggestions; - })) - .handler(this::execute)); - } + // don't suggest any words they have already typed + List suggestions = new ArrayList<>(); + SUGGESTIONS.forEach(suggestions::add); + suggestions.removeAll(inputs); + return suggestions; + })) + .handler(this::execute)); + } @Override public void execute(CommandContext context) { @@ -113,13 +113,15 @@ public class DumpCommand extends GeyserCommand { source.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.dump.collecting", source.locale())); String dumpData; try { + DumpInfo dump = new DumpInfo(geyser, addLog); + if (offlineDump) { DefaultPrettyPrinter prettyPrinter = new DefaultPrettyPrinter(); // Make arrays easier to read prettyPrinter.indentArraysWith(new DefaultIndenter(" ", "\n")); - dumpData = MAPPER.writer(prettyPrinter).writeValueAsString(new DumpInfo(addLog)); + dumpData = MAPPER.writer(prettyPrinter).writeValueAsString(dump); } else { - dumpData = MAPPER.writeValueAsString(new DumpInfo(addLog)); + dumpData = MAPPER.writeValueAsString(dump); } } catch (IOException e) { source.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.commands.dump.collect_error", source.locale())); 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 6989dc10a..515e1a629 100644 --- a/core/src/main/java/org/geysermc/geyser/dump/DumpInfo.java +++ b/core/src/main/java/org/geysermc/geyser/dump/DumpInfo.java @@ -81,7 +81,7 @@ public class DumpInfo { private final FlagsInfo flagsInfo; private final List extensionInfo; - public DumpInfo(boolean addLog) { + public DumpInfo(GeyserImpl geyser, boolean addLog) { this.versionInfo = new VersionInfo(); this.cpuCount = Runtime.getRuntime().availableProcessors(); @@ -91,7 +91,7 @@ public class DumpInfo { this.gitInfo = new GitInfo(GeyserImpl.BUILD_NUMBER, GeyserImpl.COMMIT.substring(0, 7), GeyserImpl.COMMIT, GeyserImpl.BRANCH, GeyserImpl.REPOSITORY); - this.config = GeyserImpl.getInstance().getConfig(); + this.config = geyser.getConfig(); this.floodgate = new Floodgate(); String md5Hash = "unknown"; @@ -107,7 +107,7 @@ public class DumpInfo { //noinspection UnstableApiUsage sha256Hash = byteSource.hash(Hashing.sha256()).toString(); } catch (Exception e) { - if (GeyserImpl.getInstance().getConfig().isDebugMode()) { + if (this.config.isDebugMode()) { e.printStackTrace(); } } @@ -116,18 +116,22 @@ public class DumpInfo { this.ramInfo = new RamInfo(); if (addLog) { - this.logsInfo = new LogsInfo(); + this.logsInfo = new LogsInfo(geyser); } this.userPlatforms = new Object2IntOpenHashMap<>(); - for (GeyserSession session : GeyserImpl.getInstance().getSessionManager().getAllSessions()) { + for (GeyserSession session : geyser.getSessionManager().getAllSessions()) { DeviceOs device = session.getClientData().getDeviceOs(); userPlatforms.put(device, userPlatforms.getOrDefault(device, 0) + 1); } - this.connectionAttempts = GeyserImpl.getInstance().getGeyserServer().getConnectionAttempts(); + if (geyser.getGeyserServer() != null) { + this.connectionAttempts = geyser.getGeyserServer().getConnectionAttempts(); + } else { + this.connectionAttempts = 0; // Fallback if Geyser failed to fully startup + } - this.bootstrapInfo = GeyserImpl.getInstance().getBootstrap().getDumpInfo(); + this.bootstrapInfo = geyser.getBootstrap().getDumpInfo(); this.flagsInfo = new FlagsInfo(); @@ -244,10 +248,10 @@ public class DumpInfo { public static class LogsInfo { private String link; - public LogsInfo() { + public LogsInfo(GeyserImpl geyser) { try { Map fields = new HashMap<>(); - fields.put("content", FileUtils.readAllLines(GeyserImpl.getInstance().getBootstrap().getLogsPath()).collect(Collectors.joining("\n"))); + fields.put("content", FileUtils.readAllLines(geyser.getBootstrap().getLogsPath()).collect(Collectors.joining("\n"))); JsonNode logData = GeyserImpl.JSON_MAPPER.readTree(WebUtils.postForm("https://api.mclo.gs/1/log", fields)); From 523bcdc095a1fb6bf6f6bccca033418a5ad7d92a Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Sun, 4 Aug 2024 22:00:15 -0700 Subject: [PATCH 198/233] Specify 1.21.2/1.21.3 support Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .../src/main/java/org/geysermc/geyser/network/GameProtocol.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 18dee94e6..087ecf5cc 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.21.0/1.21.1") .build())); SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v686.CODEC.toBuilder() - .minecraftVersion("1.21.2") + .minecraftVersion("1.21.2/1.21.3") .build())); SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC); } From ea6b0df9b57b209077198342ace7ddacf2b805bc Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Mon, 5 Aug 2024 18:54:17 -0500 Subject: [PATCH 199/233] Remove GeyserImpl#shouldStartListener (#4935) --- .../java/org/geysermc/geyser/GeyserImpl.java | 38 ++++++++----------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 01f1a118e..5c08e34d7 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -156,12 +156,6 @@ public class GeyserImpl implements GeyserApi, EventRegistrar { private final SessionManager sessionManager = new SessionManager(); - /** - * This is used in GeyserConnect to stop the bedrock server binding to a port - */ - @Setter - private static boolean shouldStartListener = true; - private FloodgateCipher cipher; private FloodgateSkinUploader skinUploader; private NewsHandler newsHandler; @@ -435,24 +429,22 @@ public class GeyserImpl implements GeyserApi, EventRegistrar { bedrockThreadCount = Math.max(1, SystemPropertyUtil.getInt("io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2)); } - if (shouldStartListener) { - this.geyserServer = new GeyserServer(this, bedrockThreadCount); - this.geyserServer.bind(new InetSocketAddress(config.getBedrock().address(), config.getBedrock().port())) - .whenComplete((avoid, throwable) -> { - if (throwable == null) { - logger.info(GeyserLocale.getLocaleStringLog("geyser.core.start", config.getBedrock().address(), - String.valueOf(config.getBedrock().port()))); - } else { - String address = config.getBedrock().address(); - int port = config.getBedrock().port(); - logger.severe(GeyserLocale.getLocaleStringLog("geyser.core.fail", address, String.valueOf(port))); - if (!"0.0.0.0".equals(address)) { - logger.info(Component.text("Suggestion: try setting `address` under `bedrock` in the Geyser config back to 0.0.0.0", NamedTextColor.GREEN)); - logger.info(Component.text("Then, restart this server.", NamedTextColor.GREEN)); - } + this.geyserServer = new GeyserServer(this, bedrockThreadCount); + this.geyserServer.bind(new InetSocketAddress(config.getBedrock().address(), config.getBedrock().port())) + .whenComplete((avoid, throwable) -> { + if (throwable == null) { + logger.info(GeyserLocale.getLocaleStringLog("geyser.core.start", config.getBedrock().address(), + String.valueOf(config.getBedrock().port()))); + } else { + String address = config.getBedrock().address(); + int port = config.getBedrock().port(); + logger.severe(GeyserLocale.getLocaleStringLog("geyser.core.fail", address, String.valueOf(port))); + if (!"0.0.0.0".equals(address)) { + logger.info(Component.text("Suggestion: try setting `address` under `bedrock` in the Geyser config back to 0.0.0.0", NamedTextColor.GREEN)); + logger.info(Component.text("Then, restart this server.", NamedTextColor.GREEN)); } - }).join(); - } + } + }).join(); if (config.getRemote().authType() == AuthType.FLOODGATE) { try { From 83d8c19824c9fec4218a028d0d0e833f7abe13c4 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Tue, 6 Aug 2024 12:56:10 +0100 Subject: [PATCH 200/233] Make missing locale log as debug (#4940) --- core/src/main/java/org/geysermc/geyser/text/GeyserLocale.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 28fd6f9a4..b8867c356 100644 --- a/core/src/main/java/org/geysermc/geyser/text/GeyserLocale.java +++ b/core/src/main/java/org/geysermc/geyser/text/GeyserLocale.java @@ -150,7 +150,7 @@ public class GeyserLocale { } else { if (!validLocalLanguage) { // Don't warn on missing locales if a local file has been found - bootstrap.getGeyserLogger().warning("Missing locale: " + locale); + bootstrap.getGeyserLogger().debug("Missing locale: " + locale); } } From 54c43f2b022f1be1fdd6bda2c3603372369c8c3c Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Tue, 6 Aug 2024 18:36:34 -0500 Subject: [PATCH 201/233] Suppress address in bind log if it is 0.0.0.0 (#4160) Co-authored-by: onebeastchris --- .../main/java/org/geysermc/geyser/GeyserImpl.java | 15 ++++++++++----- core/src/main/resources/languages | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 5c08e34d7..8febf4d21 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -432,13 +432,18 @@ public class GeyserImpl implements GeyserApi, EventRegistrar { this.geyserServer = new GeyserServer(this, bedrockThreadCount); this.geyserServer.bind(new InetSocketAddress(config.getBedrock().address(), config.getBedrock().port())) .whenComplete((avoid, throwable) -> { + String address = config.getBedrock().address(); + String port = String.valueOf(config.getBedrock().port()); // otherwise we get commas + if (throwable == null) { - logger.info(GeyserLocale.getLocaleStringLog("geyser.core.start", config.getBedrock().address(), - String.valueOf(config.getBedrock().port()))); + if ("0.0.0.0".equals(address)) { + // basically just hide it in the log because some people get confused and try to change it + logger.info(GeyserLocale.getLocaleStringLog("geyser.core.start.ip_suppressed", port)); + } else { + logger.info(GeyserLocale.getLocaleStringLog("geyser.core.start", address, port)); + } } else { - String address = config.getBedrock().address(); - int port = config.getBedrock().port(); - logger.severe(GeyserLocale.getLocaleStringLog("geyser.core.fail", address, String.valueOf(port))); + logger.severe(GeyserLocale.getLocaleStringLog("geyser.core.fail", address, port)); if (!"0.0.0.0".equals(address)) { logger.info(Component.text("Suggestion: try setting `address` under `bedrock` in the Geyser config back to 0.0.0.0", NamedTextColor.GREEN)); logger.info(Component.text("Then, restart this server.", NamedTextColor.GREEN)); diff --git a/core/src/main/resources/languages b/core/src/main/resources/languages index 60b20023a..a943a1bb9 160000 --- a/core/src/main/resources/languages +++ b/core/src/main/resources/languages @@ -1 +1 @@ -Subproject commit 60b20023a92f084aba895ab0336e70fa7fb311fb +Subproject commit a943a1bb910f58caa61f14bafacbc622bd48a694 From 069d35c6422a05a74f960d2fdb5d2788823ff722 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 6 Aug 2024 22:08:27 -0400 Subject: [PATCH 202/233] Likely fix for #2573 Tested working on Paper 1.21 --- .../translator/protocol/java/JavaCommandsTranslator.java | 8 ++++++++ 1 file changed, 8 insertions(+) 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 4c817ba01..01da23809 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 @@ -76,6 +76,9 @@ public class JavaCommandsTranslator extends PacketTranslator Date: Tue, 6 Aug 2024 22:09:01 -0400 Subject: [PATCH 203/233] New files for .gitignore --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a44afd242..aff61aa60 100644 --- a/.gitignore +++ b/.gitignore @@ -249,6 +249,8 @@ locales/ /packs/ /dump.json /saved-refresh-tokens.json +/saved-auth-chains.json /custom_mappings/ /languages/ -/custom-skulls.yml \ No newline at end of file +/custom-skulls.yml +/permissions.yml From 86d0a4720631513c0446558bb3bd53a121050eb8 Mon Sep 17 00:00:00 2001 From: RK_01 <50594595+RaphiMC@users.noreply.github.com> Date: Thu, 8 Aug 2024 13:25:06 +0200 Subject: [PATCH 204/233] Fix floodgate not working with the default config (#4951) --- .../geyser/platform/viaproxy/GeyserViaProxyPlugin.java | 3 +++ bootstrap/viaproxy/src/main/resources/viaproxy.yml | 2 +- gradle/libs.versions.toml | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) 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 1eed778f2..5551b9755 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 @@ -155,6 +155,9 @@ public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserBootst // 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); } + if (this.config.getRemote().authType() == AuthType.FLOODGATE) { + ViaProxy.getConfig().setPassthroughBungeecordPlayerInfo(true); + } } @Override diff --git a/bootstrap/viaproxy/src/main/resources/viaproxy.yml b/bootstrap/viaproxy/src/main/resources/viaproxy.yml index 66fbdb932..89fc612cd 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.1" +min-version: "3.3.2" diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7a81ed923..2ed67e96c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -30,7 +30,7 @@ cloud-minecraft-modded = "2.0.0-beta.7" commodore = "2.2" bungeecord = "a7c6ede" velocity = "3.3.0-SNAPSHOT" -viaproxy = "3.2.1" +viaproxy = "3.3.2-SNAPSHOT" fabric-loader = "0.15.11" fabric-api = "0.100.1+1.21" neoforge-minecraft = "21.0.0-beta" From f5b7cc725b9bdb8ecb2e554947fed10e0cc360a1 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Thu, 8 Aug 2024 15:55:14 -0400 Subject: [PATCH 205/233] Fix mangrove propagule age (#4949) --- 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 597dcd3a7..698fd2b10 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 597dcd3a78d0896638788f4b966eaa8554cf0b43 +Subproject commit 698fd2b108a9e53f1e47b8cfdc122651b70d6059 From ee0b34e49033feda757f5e1a72e6a87211514476 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 9 Aug 2024 02:15:08 +0200 Subject: [PATCH 206/233] Indicate 1.21.1 Java support - Indicate 1.21.1 support on modrinth/in the README.md - Add all supported versions of Geyser-Spigot to modrinth (#4952) --- README.md | 2 +- bootstrap/spigot/build.gradle.kts | 2 ++ .../kotlin/geyser.modrinth-uploading-conventions.gradle.kts | 4 ++-- gradle/libs.versions.toml | 4 ++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 8eac49a24..bc60a1847 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,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! ## Supported Versions -Geyser is currently supporting Minecraft Bedrock 1.20.80 - 1.21.3 and Minecraft Java Server 1.21. For more info please see [here](https://geysermc.org/wiki/geyser/supported-versions/). +Geyser is currently supporting Minecraft Bedrock 1.20.80 - 1.21.3 and Minecraft Java Server 1.21/1.21.1. For more info please see [here](https://geysermc.org/wiki/geyser/supported-versions/). ## Setting Up Take a look [here](https://geysermc.org/wiki/geyser/setup/) for how to set up Geyser. diff --git a/bootstrap/spigot/build.gradle.kts b/bootstrap/spigot/build.gradle.kts index 0a1271145..f680b1949 100644 --- a/bootstrap/spigot/build.gradle.kts +++ b/bootstrap/spigot/build.gradle.kts @@ -81,5 +81,7 @@ tasks.withType { modrinth { uploadFile.set(tasks.getByPath("shadowJar")) + gameVersions.addAll("1.16.5", "1.17", "1.17.1", "1.18", "1.18.1", "1.18.2", "1.19", + "1.19.1", "1.19.2", "1.19.3", "1.19.4", "1.20", "1.20.1", "1.20.2", "1.20.3", "1.20.4", "1.20.5", "1.20.6") loaders.addAll("spigot", "paper") } diff --git a/build-logic/src/main/kotlin/geyser.modrinth-uploading-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.modrinth-uploading-conventions.gradle.kts index d710ae1a2..fe2284137 100644 --- a/build-logic/src/main/kotlin/geyser.modrinth-uploading-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.modrinth-uploading-conventions.gradle.kts @@ -11,8 +11,8 @@ modrinth { versionNumber.set(project.version as String + "-" + System.getenv("BUILD_NUMBER")) versionType.set("beta") changelog.set(System.getenv("CHANGELOG") ?: "") - gameVersions.add(libs.minecraft.get().version as String) + gameVersions.addAll("1.21", libs.minecraft.get().version as String) failSilently.set(true) syncBodyFrom.set(rootProject.file("README.md").readText()) -} \ No newline at end of file +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2ed67e96c..b141d9989 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -33,10 +33,10 @@ velocity = "3.3.0-SNAPSHOT" viaproxy = "3.3.2-SNAPSHOT" fabric-loader = "0.15.11" fabric-api = "0.100.1+1.21" -neoforge-minecraft = "21.0.0-beta" +neoforge-minecraft = "21.1.1" mixin = "0.8.5" mixinextras = "0.3.5" -minecraft = "1.21" +minecraft = "1.21.1" # plugin versions indra = "3.1.3" From cd897feb1b60bcad6362a3027c95cad84b179441 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 9 Aug 2024 11:35:25 +0200 Subject: [PATCH 207/233] Unify repository definition (#4953) * Unify repository definition * Remove duplicate repo * Update build-logic/src/main/kotlin/geyser.build-logic.gradle.kts Co-authored-by: Konicai <71294714+Konicai@users.noreply.github.com> --------- Co-authored-by: Konicai <71294714+Konicai@users.noreply.github.com> --- .../main/kotlin/geyser.build-logic.gradle.kts | 45 ++++++++++++++++++ .../geyser.modded-conventions.gradle.kts | 10 +--- settings.gradle.kts | 46 ------------------- 3 files changed, 46 insertions(+), 55 deletions(-) diff --git a/build-logic/src/main/kotlin/geyser.build-logic.gradle.kts b/build-logic/src/main/kotlin/geyser.build-logic.gradle.kts index e69de29bb..b6168507e 100644 --- a/build-logic/src/main/kotlin/geyser.build-logic.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.build-logic.gradle.kts @@ -0,0 +1,45 @@ +repositories { + // mavenLocal() + + mavenCentral() + + // Floodgate, Cumulus etc. + maven("https://repo.opencollab.dev/main") + + // Paper, Velocity + maven("https://repo.papermc.io/repository/maven-public") + + // Spigot + maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots") { + mavenContent { snapshotsOnly() } + } + + // BungeeCord + maven("https://oss.sonatype.org/content/repositories/snapshots") { + mavenContent { snapshotsOnly() } + } + + // NeoForge + maven("https://maven.neoforged.net/releases") { + mavenContent { releasesOnly() } + } + + // Minecraft + maven("https://libraries.minecraft.net") { + name = "minecraft" + mavenContent { releasesOnly() } + } + + // ViaVersion + maven("https://repo.viaversion.com") { + name = "viaversion" + } + + // Jitpack for e.g. MCPL + maven("https://jitpack.io") { + content { includeGroupByRegex("com\\.github\\..*") } + } + + // For Adventure snapshots + maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") +} 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 20d14c443..8a6602778 100644 --- a/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts @@ -5,6 +5,7 @@ import org.gradle.kotlin.dsl.dependencies import org.gradle.kotlin.dsl.maven plugins { + id("geyser.build-logic") id("geyser.publish-conventions") id("architectury-plugin") id("dev.architectury.loom") @@ -116,12 +117,3 @@ dependencies { minecraft(libs.minecraft) mappings(loom.officialMojangMappings()) } - -repositories { - // mavenLocal() - maven("https://repo.opencollab.dev/main") - 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") -} diff --git a/settings.gradle.kts b/settings.gradle.kts index a39bfa3d2..9aaf6ba59 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -2,52 +2,6 @@ enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") -dependencyResolutionManagement { - repositories { - // mavenLocal() - - // Floodgate, Cumulus etc. - maven("https://repo.opencollab.dev/main") - - // Paper, Velocity - maven("https://repo.papermc.io/repository/maven-public") - // Spigot - maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots") { - mavenContent { snapshotsOnly() } - } - - // BungeeCord - maven("https://oss.sonatype.org/content/repositories/snapshots") { - mavenContent { snapshotsOnly() } - } - - // NeoForge - maven("https://maven.neoforged.net/releases") { - mavenContent { releasesOnly() } - } - - // Minecraft - maven("https://libraries.minecraft.net") { - name = "minecraft" - mavenContent { releasesOnly() } - } - - mavenCentral() - - // ViaVersion - maven("https://repo.viaversion.com") { - name = "viaversion" - } - - maven("https://jitpack.io") { - content { includeGroupByRegex("com\\.github\\..*") } - } - - // For Adventure snapshots - maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") - } -} - pluginManagement { repositories { gradlePluginPortal() From 41e65b0fcc5d4c905b4c6bc21a25d3c7b464ba81 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 9 Aug 2024 12:53:32 +0200 Subject: [PATCH 208/233] Bump minecraftauth dependency (#4943) * Bump minecraftauth to snapshot build fixing rare issues with Geyser-Spigot --- 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 b141d9989..b8c80d0bd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,7 +12,7 @@ gson = "2.3.1" # Provided by Spigot 1.8.8 websocket = "1.5.1" protocol = "3.0.0.Beta2-20240704.153116-14" raknet = "1.0.0.CR3-20240416.144209-1" -minecraftauth = "4.1.0" +minecraftauth = "4.1.1-20240806.235051-7" mcprotocollib = "1.21-20240725.013034-16" adventure = "4.14.0" adventure-platform = "4.3.0" From d3ea65196bf4f75c4500830059d6a0612eba8599 Mon Sep 17 00:00:00 2001 From: chris Date: Sun, 11 Aug 2024 00:50:27 +0200 Subject: [PATCH 209/233] Feature: Detect incorrect proxy setups (#4941) * Feature: Detect & warn about incorrect proxy setups on Spigot platforms * Properly disable Geyser if we failed to load --- .../bungeecord/GeyserBungeePlugin.java | 6 +--- .../platform/mod/GeyserModBootstrap.java | 5 +++ .../platform/spigot/GeyserSpigotPlugin.java | 33 +++++++++++++++++-- .../velocity/GeyserVelocityPlugin.java | 4 +++ .../viaproxy/GeyserViaProxyPlugin.java | 4 +++ core/src/main/resources/languages | 2 +- 6 files changed, 45 insertions(+), 9 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 1c0049231..e2735c80e 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 @@ -71,9 +71,6 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { private IGeyserPingPassthrough geyserBungeePingPassthrough; private GeyserImpl geyser; - // We can't disable the plugin; hence we need to keep track of it manually - private boolean disabled; - @Override public void onLoad() { onGeyserInitialize(); @@ -98,7 +95,6 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { } if (!this.loadConfig()) { - disabled = true; return; } this.geyserLogger.setDebug(geyserConfig.isDebugMode()); @@ -112,7 +108,7 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { @Override public void onEnable() { - if (disabled) { + if (geyser == null) { return; // Config did not load properly! } // Big hack - Bungee does not provide us an event to listen to, so schedule a repeating 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 f11b5fbd6..69d6dc9a4 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 @@ -89,6 +89,11 @@ public abstract class GeyserModBootstrap implements GeyserBootstrap { } public void onGeyserEnable() { + // "Disabling" a mod isn't possible; so if we fail to initialize we need to manually stop here + if (geyser == null) { + return; + } + if (GeyserImpl.getInstance().isReloading()) { if (!loadConfig()) { return; 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 3bb44a4bc..a2d52ce5a 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 @@ -117,7 +117,6 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server.message", "1.13.2")); geyserLogger.error(""); geyserLogger.error("*********************************************"); - Bukkit.getPluginManager().disablePlugin(this); return; } @@ -131,7 +130,6 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_server_type.message", "Paper")); geyserLogger.error(""); geyserLogger.error("*********************************************"); - Bukkit.getPluginManager().disablePlugin(this); return; } } @@ -144,10 +142,25 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { geyserLogger.error("This version of Spigot is using an outdated version of netty. Please use Paper instead!"); geyserLogger.error(""); geyserLogger.error("*********************************************"); - Bukkit.getPluginManager().disablePlugin(this); return; } + try { + // Check spigot config for BungeeCord mode + if (Bukkit.getServer().spigot().getConfig().getBoolean("settings.bungeecord")) { + warnInvalidProxySetups("BungeeCord"); + return; + } + + // Now: Check for velocity mode - deliberately after checking bungeecord because this is a paper only option + if (Bukkit.getServer().spigot().getPaperConfig().getBoolean("proxies.velocity.enabled")) { + warnInvalidProxySetups("Velocity"); + return; + } + } catch (NoSuchMethodError e) { + // no-op + } + if (!loadConfig()) { return; } @@ -162,6 +175,11 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { @Override public void onEnable() { + // Disabling the plugin in onLoad() is not supported; we need to manually stop here + if (geyser == null) { + return; + } + // Create command manager early so we can add Geyser extension commands var sourceConverter = new CommandSourceConverter<>( CommandSender.class, @@ -458,4 +476,13 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { return true; } + + private void warnInvalidProxySetups(String platform) { + geyserLogger.error("*********************************************"); + geyserLogger.error(""); + geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_proxy_backend", platform)); + geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.bootstrap.setup_guide", "https://geysermc.org/wiki/geyser/setup/")); + geyserLogger.error(""); + geyserLogger.error("*********************************************"); + } } 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 868cdbf8e..413355813 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 @@ -113,6 +113,10 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { @Override public void onGeyserEnable() { + // If e.g. the config failed to load, GeyserImpl was not loaded and we cannot start + if (geyser == null) { + return; + } if (GeyserImpl.getInstance().isReloading()) { if (!loadConfig()) { return; 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 5551b9755..b5e614468 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 @@ -132,6 +132,10 @@ public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserBootst @Override public void onGeyserEnable() { + // If e.g. the config failed to load, GeyserImpl was not loaded and we cannot start + if (geyser == null) { + return; + } boolean reloading = geyser.isReloading(); if (reloading) { if (!this.loadConfig()) { diff --git a/core/src/main/resources/languages b/core/src/main/resources/languages index a943a1bb9..7499daf71 160000 --- a/core/src/main/resources/languages +++ b/core/src/main/resources/languages @@ -1 +1 @@ -Subproject commit a943a1bb910f58caa61f14bafacbc622bd48a694 +Subproject commit 7499daf712ad6de70a07fba471b51b4ad92315c5 From 10281a839f13547f511005ef5304c07459a60be8 Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Sun, 11 Aug 2024 01:58:31 +0200 Subject: [PATCH 210/233] Bump version to 2.4.2 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 10d236a1b..814529d6c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,5 +7,5 @@ org.gradle.vfs.watch=false group=org.geysermc id=geyser -version=2.4.1-SNAPSHOT +version=2.4.2-SNAPSHOT description=Allows for players from Minecraft: Bedrock Edition to join Minecraft: Java Edition servers. From ce62824899e59990e7720fb4a557d172b6f075e6 Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 12 Aug 2024 23:29:00 +0200 Subject: [PATCH 211/233] Feature: Add method to close forms in the API (#4957) * Add closeForm api method * Move version check to GameProtocol --- .../geyser/api/connection/GeyserConnection.java | 15 ++++++++++----- .../org/geysermc/geyser/network/GameProtocol.java | 4 ++++ .../geysermc/geyser/session/GeyserSession.java | 9 +++++++++ 3 files changed, 23 insertions(+), 5 deletions(-) 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 ba559a462..0a580f975 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 @@ -60,6 +60,16 @@ public interface GeyserConnection extends Connection, CommandSource { */ @NonNull EntityData entities(); + /** + * Returns the current ping of the connection. + */ + int ping(); + + /** + * Closes the currently open form on the client. + */ + void closeForm(); + /** * @param javaId the Java entity ID to look up. * @return a {@link GeyserEntity} if present in this connection's entity tracker. @@ -132,9 +142,4 @@ public interface GeyserConnection extends Connection, CommandSource { @Deprecated @NonNull Set fogEffects(); - - /** - * Returns the current ping of the connection. - */ - int ping(); } 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 087ecf5cc..422fa3d5a 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -97,6 +97,10 @@ public final class GameProtocol { return session.getUpstream().getProtocolVersion() < Bedrock_v685.CODEC.getProtocolVersion(); } + public static boolean isPre1_21_2(GeyserSession session) { + return session.getUpstream().getProtocolVersion() < Bedrock_v686.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 9a990865e..9137c4756 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -79,6 +79,7 @@ import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket; import org.cloudburstmc.protocol.bedrock.packet.BiomeDefinitionListPacket; import org.cloudburstmc.protocol.bedrock.packet.CameraPresetsPacket; import org.cloudburstmc.protocol.bedrock.packet.ChunkRadiusUpdatedPacket; +import org.cloudburstmc.protocol.bedrock.packet.ClientboundCloseFormPacket; import org.cloudburstmc.protocol.bedrock.packet.CraftingDataPacket; import org.cloudburstmc.protocol.bedrock.packet.CreativeContentPacket; import org.cloudburstmc.protocol.bedrock.packet.EmoteListPacket; @@ -140,6 +141,7 @@ import org.geysermc.geyser.item.type.BlockItem; import org.geysermc.geyser.level.BedrockDimension; import org.geysermc.geyser.level.JavaDimension; 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; @@ -2114,6 +2116,13 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { return (int) Math.floor(rakSessionCodec.getPing()); } + @Override + public void closeForm() { + if (!GameProtocol.isPre1_21_2(this)) { + sendUpstreamPacket(new ClientboundCloseFormPacket()); + } + } + public void addCommandEnum(String name, String enums) { softEnumPacket(name, SoftEnumUpdateType.ADD, enums); } From ee43ef836925716fdf8eab26befd405836c56259 Mon Sep 17 00:00:00 2001 From: chris Date: Tue, 13 Aug 2024 01:45:25 +0200 Subject: [PATCH 212/233] Disable the plugin if we failed to load on Spigot (#4960) --- .../geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java | 3 ++- 1 file changed, 2 insertions(+), 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 a2d52ce5a..c52927a83 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 @@ -175,8 +175,9 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { @Override public void onEnable() { - // Disabling the plugin in onLoad() is not supported; we need to manually stop here + // Disabling the plugin in onLoad() is not supported; we need to manually stop here and disable ourselves if (geyser == null) { + Bukkit.getPluginManager().disablePlugin(this); return; } From 8f7d512073532cba3b761b99830ccbcf7a28cddc Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 13 Aug 2024 13:42:20 -0400 Subject: [PATCH 213/233] Fix armor not being visible on 1.21.20 --- .../geysermc/geyser/entity/type/LivingEntity.java | 6 ++++++ .../java/entity/JavaSetEquipmentTranslator.java | 13 +++++++++++-- 2 files changed, 17 insertions(+), 2 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 2a1bc1188..1dfe02b09 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 @@ -74,6 +74,7 @@ public class LivingEntity extends Entity { protected ItemData chestplate = ItemData.AIR; protected ItemData leggings = ItemData.AIR; protected ItemData boots = ItemData.AIR; + protected ItemData body = ItemData.AIR; protected ItemData hand = ItemData.AIR; protected ItemData offhand = ItemData.AIR; @@ -112,6 +113,10 @@ public class LivingEntity extends Entity { this.chestplate = ItemTranslator.translateToBedrock(session, stack); } + public void setBody(ItemStack stack) { + this.body = ItemTranslator.translateToBedrock(session, stack); + } + public void setLeggings(ItemStack stack) { this.leggings = ItemTranslator.translateToBedrock(session, stack); } @@ -323,6 +328,7 @@ public class LivingEntity extends Entity { armorEquipmentPacket.setChestplate(chestplate); armorEquipmentPacket.setLeggings(leggings); armorEquipmentPacket.setBoots(boots); + armorEquipmentPacket.setBody(body); session.sendUpstreamPacket(armorEquipmentPacket); } 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 07dcced47..11178115a 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 @@ -29,6 +29,7 @@ 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.network.GameProtocol; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.skin.FakeHeadProvider; import org.geysermc.geyser.translator.protocol.PacketTranslator; @@ -72,11 +73,19 @@ public class JavaSetEquipmentTranslator extends PacketTranslator { - // BODY is sent for llamas with a carpet equipped, as of 1.20.5 + case CHESTPLATE -> { livingEntity.setChestplate(stack); armorUpdated = true; } + case BODY -> { + // BODY is sent for llamas with a carpet equipped, as of 1.20.5 + if (GameProtocol.isPre1_21_2(session)) { + livingEntity.setChestplate(stack); + } else { + livingEntity.setBody(stack); + } + armorUpdated = true; + } case LEGGINGS -> { livingEntity.setLeggings(stack); armorUpdated = true; From 0bc39d5a191777fcded4d9435393c511a3f37f43 Mon Sep 17 00:00:00 2001 From: chris Date: Tue, 13 Aug 2024 22:05:40 +0200 Subject: [PATCH 214/233] Remove old config option (#4962) --- core/src/main/resources/config.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index a5fe2072b..15d3a20a6 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -54,9 +54,6 @@ remote: # For plugin versions, it's recommended to keep the `address` field to "auto" so Floodgate support is automatically configured. # If Floodgate is installed and `address:` is set to "auto", then "auth-type: floodgate" will automatically be used. auth-type: online - # Allow for password-based authentication methods through Geyser. Only useful in online mode. - # If this is false, users must authenticate to Microsoft using a code provided by Geyser on their desktop. - allow-password-authentication: true # Whether to enable PROXY protocol or not while connecting to the server. # This is useful only when: # 1) Your server supports PROXY protocol (it probably doesn't) From 4f7e9fca9cea213d5968401fdfc60a2495d6bec9 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Wed, 14 Aug 2024 16:07:15 -0400 Subject: [PATCH 215/233] Update Protocol and fix item stack encoding --- .../geyser/translator/inventory/InventoryTranslator.java | 7 ++++--- gradle/libs.versions.toml | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) 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 ce1022936..546ebda19 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 @@ -29,6 +29,7 @@ import it.unimi.dsi.fastutil.ints.*; import lombok.AllArgsConstructor; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; +import org.cloudburstmc.protocol.bedrock.data.inventory.FullContainerName; 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.*; @@ -894,11 +895,11 @@ public abstract class InventoryTranslator { List containerEntries = new ArrayList<>(); for (Map.Entry> entry : containerMap.entrySet()) { - containerEntries.add(new ItemStackResponseContainer(entry.getKey(), entry.getValue(), null)); + containerEntries.add(new ItemStackResponseContainer(entry.getKey(), entry.getValue(), new FullContainerName(entry.getKey(), 0))); } ItemStackResponseSlot cursorEntry = makeItemEntry(0, session.getPlayerInventory().getCursor()); - containerEntries.add(new ItemStackResponseContainer(ContainerSlotType.CURSOR, Collections.singletonList(cursorEntry), null)); + containerEntries.add(new ItemStackResponseContainer(ContainerSlotType.CURSOR, Collections.singletonList(cursorEntry), new FullContainerName(ContainerSlotType.CURSOR, 0))); return containerEntries; } @@ -952,4 +953,4 @@ public abstract class InventoryTranslator { TRANSFER, DONE } -} \ No newline at end of file +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f46dfdaed..a4b274c80 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,7 @@ 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" -protocol = "3.0.0.Beta3-20240726.112706-2" +protocol = "3.0.0.Beta3-20240814.133201-7" raknet = "1.0.0.CR3-20240416.144209-1" minecraftauth = "4.1.1-20240806.235051-7" mcprotocollib = "1.21-20240725.013034-16" From 34bab14860db0476129fb86280b3c9b69293e5c8 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Thu, 15 Aug 2024 03:03:34 -0400 Subject: [PATCH 216/233] Emulate client side vehicle movement (#4648) * WIP client side vehicles * Address reviews and remove use of Optional * Only tick active vehicle * Track world ticks * Fixes for Camel dash and pose transition * Remove vehicle parameter * Start using blocks refactor * Update BlockRegistryPopulator * Update blocks * Support step height attribute * Use climbable block tag and TrapDoorBlock * Lock camel rotation if stationary * Fix boost ticking * Keep cache of surrounding blocks * Fix bug causing BoundingBox position to change in CollisionManager * Clamp user input * Support weaving status effect * Support gravity attribute * Piston support * Tick boost for Pig and Strider if any player is controlling * Submodule * Address some reviews * Support world border * Optimize world border check * Small optimizations * Add comments --- .../geyser/entity/EntityDefinitions.java | 6 +- .../geyser/entity/type/LivingEntity.java | 49 +- .../entity/type/living/animal/PigEntity.java | 63 +- .../type/living/animal/StriderEntity.java | 68 +- .../type/living/animal/horse/CamelEntity.java | 67 +- .../type/player/SessionPlayerEntity.java | 23 + .../vehicle/BoostableVehicleComponent.java | 60 ++ .../entity/vehicle/CamelVehicleComponent.java | 153 +++ .../geyser/entity/vehicle/ClientVehicle.java | 46 + .../entity/vehicle/VehicleComponent.java | 964 ++++++++++++++++++ .../geyser/inventory/PlayerInventory.java | 10 + .../inventory/item/StoredItemMappings.java | 4 + .../geysermc/geyser/level/JavaDimension.java | 8 +- .../geyser/level/block/BlockStateValues.java | 56 +- .../geysermc/geyser/level/block/Fluid.java | 32 + .../geyser/level/physics/BoundingBox.java | 38 +- .../level/physics/CollisionManager.java | 93 +- .../geyser/level/physics/Direction.java | 1 + .../geyser/session/GeyserSession.java | 21 + .../geyser/session/cache/PistonCache.java | 26 +- .../geyser/session/cache/WorldBorder.java | 52 + .../translator/collision/BlockCollision.java | 18 + .../level/block/entity/PistonBlockEntity.java | 60 +- .../bedrock/BedrockPlayerInputTranslator.java | 2 + .../player/BedrockMovePlayerTranslator.java | 5 +- .../player/BedrockRiderJumpTranslator.java | 2 + .../protocol/java/JavaRespawnTranslator.java | 1 + .../entity/JavaMoveVehicleTranslator.java | 5 + .../entity/JavaRemoveMobEffectTranslator.java | 9 +- .../entity/JavaSetPassengersTranslator.java | 9 + .../entity/JavaTeleportEntityTranslator.java | 5 + .../entity/JavaUpdateMobEffectTranslator.java | 10 +- .../java/level/JavaSetTimeTranslator.java | 2 + gradle/libs.versions.toml | 2 +- 34 files changed, 1903 insertions(+), 67 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/entity/vehicle/BoostableVehicleComponent.java create mode 100644 core/src/main/java/org/geysermc/geyser/entity/vehicle/CamelVehicleComponent.java create mode 100644 core/src/main/java/org/geysermc/geyser/entity/vehicle/ClientVehicle.java create mode 100644 core/src/main/java/org/geysermc/geyser/entity/vehicle/VehicleComponent.java create mode 100644 core/src/main/java/org/geysermc/geyser/level/block/Fluid.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 9063c7421..5932ecf41 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -888,7 +888,7 @@ public final class EntityDefinitions { .type(EntityType.PIG) .heightAndWidth(0.9f) .addTranslator(MetadataType.BOOLEAN, (pigEntity, entityMetadata) -> pigEntity.setFlag(EntityFlag.SADDLED, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue())) - .addTranslator(null) // Boost time + .addTranslator(MetadataType.INT, PigEntity::setBoost) .build(); POLAR_BEAR = EntityDefinition.inherited(PolarBearEntity::new, ageableEntityBase) .type(EntityType.POLAR_BEAR) @@ -914,7 +914,7 @@ public final class EntityDefinitions { STRIDER = EntityDefinition.inherited(StriderEntity::new, ageableEntityBase) .type(EntityType.STRIDER) .height(1.7f).width(0.9f) - .addTranslator(null) // Boost time + .addTranslator(MetadataType.INT, StriderEntity::setBoost) .addTranslator(MetadataType.BOOLEAN, StriderEntity::setCold) .addTranslator(MetadataType.BOOLEAN, StriderEntity::setSaddled) .build(); @@ -955,7 +955,7 @@ public final class EntityDefinitions { .type(EntityType.CAMEL) .height(2.375f).width(1.7f) .addTranslator(MetadataType.BOOLEAN, CamelEntity::setDashing) - .addTranslator(null) // Last pose change tick + .addTranslator(MetadataType.LONG, CamelEntity::setLastPoseTick) .build(); HORSE = EntityDefinition.inherited(HorseEntity::new, abstractHorseEntityBase) .type(EntityType.HORSE) 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 1dfe02b09..266189e63 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,6 +41,7 @@ import org.cloudburstmc.protocol.bedrock.packet.MobEquipmentPacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.attribute.GeyserAttributeType; +import org.geysermc.geyser.entity.vehicle.ClientVehicle; import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.item.Items; import org.geysermc.geyser.registry.type.ItemMapping; @@ -294,6 +295,36 @@ public class LivingEntity extends Entity { return super.interact(hand); } + @Override + public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, float headYaw, boolean isOnGround) { + if (this instanceof ClientVehicle clientVehicle) { + if (clientVehicle.isClientControlled()) { + return; + } + clientVehicle.getVehicleComponent().moveRelative(relX, relY, relZ); + } + + super.moveRelative(relX, relY, relZ, yaw, pitch, headYaw, isOnGround); + } + + @Override + public boolean setBoundingBoxHeight(float height) { + if (valid && this instanceof ClientVehicle clientVehicle) { + clientVehicle.getVehicleComponent().setHeight(height); + } + + return super.setBoundingBoxHeight(height); + } + + @Override + public void setBoundingBoxWidth(float width) { + if (valid && this instanceof ClientVehicle clientVehicle) { + clientVehicle.getVehicleComponent().setWidth(width); + } + + super.setBoundingBoxWidth(width); + } + /** * Checks to see if a nametag interaction would go through. */ @@ -407,9 +438,25 @@ public class LivingEntity extends Entity { this.maxHealth = Math.max((float) AttributeUtils.calculateValue(javaAttribute), 1f); newAttributes.add(createHealthAttribute()); } + case GENERIC_MOVEMENT_SPEED -> { + AttributeData attributeData = calculateAttribute(javaAttribute, GeyserAttributeType.MOVEMENT_SPEED); + newAttributes.add(attributeData); + if (this instanceof ClientVehicle clientVehicle) { + clientVehicle.getVehicleComponent().setMoveSpeed(attributeData.getValue()); + } + } + case GENERIC_STEP_HEIGHT -> { + if (this instanceof ClientVehicle clientVehicle) { + clientVehicle.getVehicleComponent().setStepHeight((float) AttributeUtils.calculateValue(javaAttribute)); + } + } + case GENERIC_GRAVITY -> { + if (this instanceof ClientVehicle clientVehicle) { + clientVehicle.getVehicleComponent().setGravity(AttributeUtils.calculateValue(javaAttribute)); + } + } case GENERIC_ATTACK_DAMAGE -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.ATTACK_DAMAGE)); case GENERIC_FLYING_SPEED -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.FLYING_SPEED)); - 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 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/PigEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java index 446e3e109..2ec23d673 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 @@ -27,20 +27,30 @@ 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.Vector2f; import org.cloudburstmc.math.vector.Vector3f; +import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.geyser.entity.EntityDefinition; +import org.geysermc.geyser.entity.type.Tickable; +import org.geysermc.geyser.entity.type.player.PlayerEntity; +import org.geysermc.geyser.entity.vehicle.BoostableVehicleComponent; +import org.geysermc.geyser.entity.vehicle.ClientVehicle; +import org.geysermc.geyser.entity.vehicle.VehicleComponent; 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.EntityUtils; import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractiveTag; +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; -public class PigEntity extends AnimalEntity { +public class PigEntity extends AnimalEntity implements Tickable, ClientVehicle { + private final BoostableVehicleComponent vehicleComponent = new BoostableVehicleComponent<>(this, 1.0f); public PigEntity(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); @@ -84,4 +94,55 @@ public class PigEntity extends AnimalEntity { } } } + + public void setBoost(IntEntityMetadata entityMetadata) { + vehicleComponent.startBoost(entityMetadata.getPrimitiveValue()); + } + + @Override + public void tick() { + PlayerEntity player = getPlayerPassenger(); + if (player == null) { + return; + } + + if (player == session.getPlayerEntity()) { + if (session.getPlayerInventory().isHolding(Items.CARROT_ON_A_STICK)) { + vehicleComponent.tickBoost(); + } + } else { // getHand() for session player seems to always return air + ItemDefinition itemDefinition = session.getItemMappings().getStoredItems().carrotOnAStick().getBedrockDefinition(); + if (player.getHand().getDefinition() == itemDefinition || player.getOffhand().getDefinition() == itemDefinition) { + vehicleComponent.tickBoost(); + } + } + } + + @Override + public VehicleComponent getVehicleComponent() { + return vehicleComponent; + } + + @Override + public Vector2f getAdjustedInput(Vector2f input) { + return Vector2f.UNIT_Y; + } + + @Override + public float getVehicleSpeed() { + return vehicleComponent.getMoveSpeed() * 0.225f * vehicleComponent.getBoostMultiplier(); + } + + private @Nullable PlayerEntity getPlayerPassenger() { + if (getFlag(EntityFlag.SADDLED) && !passengers.isEmpty() && passengers.get(0) instanceof PlayerEntity playerEntity) { + return playerEntity; + } + + return null; + } + + @Override + public boolean isClientControlled() { + return getPlayerPassenger() == session.getPlayerEntity() && session.getPlayerInventory().isHolding(Items.CARROT_ON_A_STICK); + } } 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 0291f75d9..e06af2786 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,23 +27,33 @@ 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.Vector2f; import org.cloudburstmc.math.vector.Vector3f; +import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; 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.entity.type.Tickable; +import org.geysermc.geyser.entity.type.player.PlayerEntity; +import org.geysermc.geyser.entity.vehicle.BoostableVehicleComponent; +import org.geysermc.geyser.entity.vehicle.ClientVehicle; +import org.geysermc.geyser.entity.vehicle.VehicleComponent; 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.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.metadata.type.IntEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import java.util.UUID; -public class StriderEntity extends AnimalEntity { +public class StriderEntity extends AnimalEntity implements Tickable, ClientVehicle { + private final BoostableVehicleComponent vehicleComponent = new BoostableVehicleComponent<>(this, 1.0f); private boolean isCold = false; public StriderEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { @@ -131,4 +141,60 @@ public class StriderEntity extends AnimalEntity { } } } + + public void setBoost(IntEntityMetadata entityMetadata) { + vehicleComponent.startBoost(entityMetadata.getPrimitiveValue()); + } + + @Override + public void tick() { + PlayerEntity player = getPlayerPassenger(); + if (player == null) { + return; + } + + if (player == session.getPlayerEntity()) { + if (session.getPlayerInventory().isHolding(Items.WARPED_FUNGUS_ON_A_STICK)) { + vehicleComponent.tickBoost(); + } + } else { // getHand() for session player seems to always return air + ItemDefinition itemDefinition = session.getItemMappings().getStoredItems().warpedFungusOnAStick().getBedrockDefinition(); + if (player.getHand().getDefinition() == itemDefinition || player.getOffhand().getDefinition() == itemDefinition) { + vehicleComponent.tickBoost(); + } + } + } + + @Override + public VehicleComponent getVehicleComponent() { + return vehicleComponent; + } + + @Override + public Vector2f getAdjustedInput(Vector2f input) { + return Vector2f.UNIT_Y; + } + + @Override + public float getVehicleSpeed() { + return vehicleComponent.getMoveSpeed() * (isCold ? 0.35f : 0.55f) * vehicleComponent.getBoostMultiplier(); + } + + private @Nullable PlayerEntity getPlayerPassenger() { + if (getFlag(EntityFlag.SADDLED) && !passengers.isEmpty() && passengers.get(0) instanceof PlayerEntity playerEntity) { + return playerEntity; + } + + return null; + } + + @Override + public boolean isClientControlled() { + return getPlayerPassenger() == session.getPlayerEntity() && session.getPlayerInventory().isHolding(Items.WARPED_FUNGUS_ON_A_STICK); + } + + @Override + public boolean canWalkOnLava() { + return true; + } } 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 ee3b2be70..3c0bf1a70 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,26 +25,36 @@ package org.geysermc.geyser.entity.type.living.animal.horse; +import org.cloudburstmc.math.vector.Vector2f; 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; import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType; 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.entity.attribute.GeyserAttributeType; +import org.geysermc.geyser.entity.vehicle.CamelVehicleComponent; +import org.geysermc.geyser.entity.vehicle.ClientVehicle; +import org.geysermc.geyser.entity.vehicle.VehicleComponent; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.tags.ItemTag; +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.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.LongEntityMetadata; import java.util.UUID; -public class CamelEntity extends AbstractHorseEntity { - +public class CamelEntity extends AbstractHorseEntity implements ClientVehicle { public static final float SITTING_HEIGHT_DIFFERENCE = 1.43F; + private final CamelVehicleComponent vehicleComponent = new CamelVehicleComponent(this); + public CamelEntity(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); @@ -111,5 +121,58 @@ public class CamelEntity extends AbstractHorseEntity { } public void setDashing(BooleanEntityMetadata entityMetadata) { + // Java sends true to show dash animation and start the dash cooldown, + // false ends the dash animation, not the cooldown. + // Bedrock shows dash animation if HAS_DASH_COOLDOWN is set and the camel is above ground + if (entityMetadata.getPrimitiveValue()) { + setFlag(EntityFlag.HAS_DASH_COOLDOWN, true); + vehicleComponent.startDashCooldown(); + } else if (!isClientControlled()) { // Don't remove dash cooldown prematurely if client is controlling + setFlag(EntityFlag.HAS_DASH_COOLDOWN, false); + } + } + + public void setLastPoseTick(LongEntityMetadata entityMetadata) { + // Tick is based on world time. If negative, the camel is sitting. + // Must be compared to world time to know if the camel is fully standing/sitting or transitioning. + vehicleComponent.setLastPoseTick(entityMetadata.getPrimitiveValue()); + } + + @Override + protected AttributeData calculateAttribute(Attribute javaAttribute, GeyserAttributeType type) { + AttributeData attributeData = super.calculateAttribute(javaAttribute, type); + if (javaAttribute.getType() == AttributeType.Builtin.GENERIC_JUMP_STRENGTH) { + vehicleComponent.setHorseJumpStrength(attributeData.getValue()); + } + return attributeData; + } + + @Override + public VehicleComponent getVehicleComponent() { + return vehicleComponent; + } + + @Override + public Vector2f getAdjustedInput(Vector2f input) { + return input.mul(0.5f, input.getY() < 0 ? 0.25f : 1.0f); + } + + @Override + public boolean isClientControlled() { + return getFlag(EntityFlag.SADDLED) && !passengers.isEmpty() && passengers.get(0) == session.getPlayerEntity(); + } + + @Override + public float getVehicleSpeed() { + float moveSpeed = vehicleComponent.getMoveSpeed(); + if (!getFlag(EntityFlag.HAS_DASH_COOLDOWN) && session.getPlayerEntity().getFlag(EntityFlag.SPRINTING)) { + return moveSpeed + 0.1f; + } + return moveSpeed; + } + + @Override + public boolean canClimb() { + return false; } } 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 b924461af..ccf2d25e6 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 @@ -29,6 +29,7 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.Getter; import lombok.Setter; 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.AttributeData; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; @@ -42,6 +43,7 @@ import org.geysermc.geyser.level.BedrockDimension; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.AttributeUtils; import org.geysermc.geyser.util.DimensionUtils; +import org.geysermc.geyser.util.MathUtils; 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; @@ -74,6 +76,16 @@ public class SessionPlayerEntity extends PlayerEntity { */ @Getter private boolean isRidingInFront; + /** + * Used when emulating client-side vehicles + */ + @Getter + private Vector2f vehicleInput = Vector2f.ZERO; + /** + * Used when emulating client-side vehicles + */ + @Getter + private int vehicleJumpStrength; private int lastAirSupply = getMaxAir(); @@ -315,6 +327,17 @@ public class SessionPlayerEntity extends PlayerEntity { this.setAirSupply(getMaxAir()); } + public void setVehicleInput(Vector2f vehicleInput) { + this.vehicleInput = Vector2f.from( + MathUtils.clamp(vehicleInput.getX(), -1.0f, 1.0f), + MathUtils.clamp(vehicleInput.getY(), -1.0f, 1.0f) + ); + } + + public void setVehicleJumpStrength(int vehicleJumpStrength) { + this.vehicleJumpStrength = MathUtils.constrain(vehicleJumpStrength, 0, 100); + } + private boolean isBelowVoidFloor() { return position.getY() < voidFloorPosition(); } diff --git a/core/src/main/java/org/geysermc/geyser/entity/vehicle/BoostableVehicleComponent.java b/core/src/main/java/org/geysermc/geyser/entity/vehicle/BoostableVehicleComponent.java new file mode 100644 index 000000000..41224012d --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/entity/vehicle/BoostableVehicleComponent.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.entity.vehicle; + +import org.cloudburstmc.math.TrigMath; +import org.geysermc.geyser.entity.type.LivingEntity; + +public class BoostableVehicleComponent extends VehicleComponent { + private int boostLength; + private int boostTicks = 1; + + public BoostableVehicleComponent(T vehicle, float stepHeight) { + super(vehicle, stepHeight); + } + + public void startBoost(int boostLength) { + this.boostLength = boostLength; + this.boostTicks = 1; + } + + public float getBoostMultiplier() { + if (isBoosting()) { + return 1.0f + 1.15f * TrigMath.sin((float) boostTicks / (float) boostLength * TrigMath.PI); + } + return 1.0f; + } + + public boolean isBoosting() { + return boostTicks <= boostLength; + } + + public void tickBoost() { + if (isBoosting()) { + boostTicks++; + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/entity/vehicle/CamelVehicleComponent.java b/core/src/main/java/org/geysermc/geyser/entity/vehicle/CamelVehicleComponent.java new file mode 100644 index 000000000..7d022ed7c --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/entity/vehicle/CamelVehicleComponent.java @@ -0,0 +1,153 @@ +/* + * 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.vehicle; + +import lombok.Setter; +import org.cloudburstmc.math.vector.Vector2f; +import org.cloudburstmc.math.vector.Vector3f; +import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; +import org.geysermc.geyser.entity.type.living.animal.horse.CamelEntity; +import org.geysermc.geyser.entity.type.player.SessionPlayerEntity; +import org.geysermc.mcprotocollib.protocol.data.game.entity.Effect; + +public class CamelVehicleComponent extends VehicleComponent { + private static final int STANDING_TICKS = 52; + private static final int DASH_TICKS = 55; + + @Setter + private float horseJumpStrength = 0.42f; // Not sent by vanilla Java server when spawned + + @Setter + private long lastPoseTick; + + private int dashTick; + private int effectJumpBoost; + + public CamelVehicleComponent(CamelEntity vehicle) { + super(vehicle, 1.5f); + } + + public void startDashCooldown() { + // tickVehicle is only called while the vehicle is mounted. Use session ticks to keep + // track of time instead of counting down + this.dashTick = vehicle.getSession().getTicks() + DASH_TICKS; + } + + @Override + public void tickVehicle() { + if (this.dashTick != 0) { + if (vehicle.getSession().getTicks() > this.dashTick) { + vehicle.setFlag(EntityFlag.HAS_DASH_COOLDOWN, false); + this.dashTick = 0; + } else { + vehicle.setFlag(EntityFlag.HAS_DASH_COOLDOWN, true); + } + } + + vehicle.setFlag(EntityFlag.CAN_DASH, vehicle.getFlag(EntityFlag.SADDLED) && !isStationary()); + vehicle.updateBedrockMetadata(); + super.tickVehicle(); + } + + @Override + public void onDismount() { + // Prevent camel from getting stuck in dash animation + vehicle.setFlag(EntityFlag.HAS_DASH_COOLDOWN, false); + vehicle.updateBedrockMetadata(); + super.onDismount(); + } + + @Override + protected boolean travel(VehicleContext ctx, float speed) { + if (vehicle.isOnGround() && isStationary()) { + vehicle.setMotion(vehicle.getMotion().mul(0, 1, 0)); + } + + return super.travel(ctx, speed); + } + + @Override + protected Vector3f getInputVelocity(VehicleContext ctx, float speed) { + if (isStationary()) { + return Vector3f.ZERO; + } + + SessionPlayerEntity player = vehicle.getSession().getPlayerEntity(); + Vector3f inputVelocity = super.getInputVelocity(ctx, speed); + float jumpStrength = player.getVehicleJumpStrength(); + + if (jumpStrength > 0) { + player.setVehicleJumpStrength(0); + + if (jumpStrength >= 90) { + jumpStrength = 1.0f; + } else { + jumpStrength = 0.4f + 0.4f * jumpStrength / 90.0f; + } + + return inputVelocity.add(Vector3f.createDirectionDeg(0, -player.getYaw()) + .mul(22.2222f * jumpStrength * this.moveSpeed * getVelocityMultiplier(ctx)) + .up(1.4285f * jumpStrength * (this.horseJumpStrength * getJumpVelocityMultiplier(ctx) + (this.effectJumpBoost * 0.1f)))); + } + + return inputVelocity; + } + + @Override + protected Vector2f getVehicleRotation() { + if (isStationary()) { + return Vector2f.from(vehicle.getYaw(), vehicle.getPitch()); + } + return super.getVehicleRotation(); + } + + /** + * Checks if the camel is sitting + * or transitioning to standing pose. + */ + private boolean isStationary() { + // Java checks if sitting using lastPoseTick + return this.lastPoseTick < 0 || vehicle.getSession().getWorldTicks() < this.lastPoseTick + STANDING_TICKS; + } + + @Override + public void setEffect(Effect effect, int effectAmplifier) { + if (effect == Effect.JUMP_BOOST) { + effectJumpBoost = effectAmplifier + 1; + } else { + super.setEffect(effect, effectAmplifier); + } + } + + @Override + public void removeEffect(Effect effect) { + if (effect == Effect.JUMP_BOOST) { + effectJumpBoost = 0; + } else { + super.removeEffect(effect); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/entity/vehicle/ClientVehicle.java b/core/src/main/java/org/geysermc/geyser/entity/vehicle/ClientVehicle.java new file mode 100644 index 000000000..e6aaf1daa --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/entity/vehicle/ClientVehicle.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.entity.vehicle; + +import org.cloudburstmc.math.vector.Vector2f; + +public interface ClientVehicle { + VehicleComponent getVehicleComponent(); + + Vector2f getAdjustedInput(Vector2f input); + + float getVehicleSpeed(); + + boolean isClientControlled(); + + default boolean canWalkOnLava() { + return false; + } + + default boolean canClimb() { + return true; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/entity/vehicle/VehicleComponent.java b/core/src/main/java/org/geysermc/geyser/entity/vehicle/VehicleComponent.java new file mode 100644 index 000000000..db703a3cb --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/entity/vehicle/VehicleComponent.java @@ -0,0 +1,964 @@ +/* + * 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.vehicle; + +import it.unimi.dsi.fastutil.objects.ObjectDoublePair; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.cloudburstmc.math.TrigMath; +import org.cloudburstmc.math.vector.Vector2f; +import org.cloudburstmc.math.vector.Vector3d; +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.MoveEntityDeltaPacket; +import org.geysermc.erosion.util.BlockPositionIterator; +import org.geysermc.geyser.entity.type.LivingEntity; +import org.geysermc.geyser.level.block.BlockStateValues; +import org.geysermc.geyser.level.block.Blocks; +import org.geysermc.geyser.level.block.Fluid; +import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.geyser.level.block.type.BedBlock; +import org.geysermc.geyser.level.block.type.Block; +import org.geysermc.geyser.level.block.type.BlockState; +import org.geysermc.geyser.level.block.type.TrapDoorBlock; +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.session.cache.tags.BlockTag; +import org.geysermc.geyser.translator.collision.BlockCollision; +import org.geysermc.geyser.translator.collision.SolidCollision; +import org.geysermc.geyser.util.BlockUtils; +import org.geysermc.geyser.util.MathUtils; +import org.geysermc.mcprotocollib.protocol.data.game.entity.Effect; +import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.AttributeType; +import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundMoveVehiclePacket; + +public class VehicleComponent { + private static final ObjectDoublePair EMPTY_FLUID_PAIR = ObjectDoublePair.of(Fluid.EMPTY, 0.0); + private static final float MAX_LOGICAL_FLUID_HEIGHT = 8.0f / BlockStateValues.NUM_FLUID_LEVELS; + private static final float BASE_SLIPPERINESS_CUBED = 0.6f * 0.6f * 0.6f; + private static final float MIN_VELOCITY = 0.003f; + + protected final T vehicle; + protected final BoundingBox boundingBox; + + protected float stepHeight; + protected float moveSpeed; + protected double gravity; + protected int effectLevitation; + protected boolean effectSlowFalling; + protected boolean effectWeaving; + + public VehicleComponent(T vehicle, float stepHeight) { + this.vehicle = vehicle; + this.stepHeight = stepHeight; + this.moveSpeed = (float) AttributeType.Builtin.GENERIC_MOVEMENT_SPEED.getDef(); + this.gravity = AttributeType.Builtin.GENERIC_GRAVITY.getDef(); + + double width = vehicle.getBoundingBoxWidth(); + double height = vehicle.getBoundingBoxHeight(); + this.boundingBox = new BoundingBox( + vehicle.getPosition().getX(), + vehicle.getPosition().getY() + height / 2, + vehicle.getPosition().getZ(), + width, height, width + ); + } + + public void setWidth(float width) { + boundingBox.setSizeX(width); + boundingBox.setSizeZ(width); + } + + public void setHeight(float height) { + boundingBox.translate(0, (height - boundingBox.getSizeY()) / 2, 0); + boundingBox.setSizeY(height); + } + + public void moveAbsolute(double x, double y, double z) { + boundingBox.setMiddleX(x); + boundingBox.setMiddleY(y + boundingBox.getSizeY() / 2); + boundingBox.setMiddleZ(z); + } + + public void moveRelative(double x, double y, double z) { + boundingBox.translate(x, y, z); + } + + public void moveRelative(Vector3d vec) { + boundingBox.translate(vec); + } + + public BoundingBox getBoundingBox() { + return this.boundingBox; + } + + public void setEffect(Effect effect, int effectAmplifier) { + switch (effect) { + case LEVITATION -> effectLevitation = effectAmplifier + 1; + case SLOW_FALLING -> effectSlowFalling = true; + case WEAVING -> effectWeaving = true; + } + } + + public void removeEffect(Effect effect) { + switch (effect) { + case LEVITATION -> effectLevitation = 0; + case SLOW_FALLING -> effectSlowFalling = false; + case WEAVING -> effectWeaving = false; + } + } + + public void setMoveSpeed(float moveSpeed) { + this.moveSpeed = moveSpeed; + } + + public float getMoveSpeed() { + return moveSpeed; + } + + public void setStepHeight(float stepHeight) { + this.stepHeight = MathUtils.clamp(stepHeight, 1.0f, 10.0f); + } + + public void setGravity(double gravity) { + this.gravity = MathUtils.constrain(gravity, -1.0, 1.0); + } + + public Vector3d correctMovement(Vector3d movement) { + return vehicle.getSession().getCollisionManager().correctMovement( + movement, boundingBox, vehicle.isOnGround(), this.stepHeight, true, vehicle.canWalkOnLava() + ); + } + + public void onMount() { + vehicle.getSession().getPlayerEntity().setVehicleInput(Vector2f.ZERO); + vehicle.getSession().getPlayerEntity().setVehicleJumpStrength(0); + } + + public void onDismount() { + // + } + + /** + * Called every session tick while the player is mounted on the vehicle. + */ + public void tickVehicle() { + if (!vehicle.isClientControlled()) { + return; + } + + VehicleContext ctx = new VehicleContext(); + ctx.loadSurroundingBlocks(); + + ObjectDoublePair fluidHeight = updateFluidMovement(ctx); + switch (fluidHeight.left()) { + case WATER -> waterMovement(ctx); + case LAVA -> { + if (vehicle.canWalkOnLava() && ctx.centerBlock().is(Blocks.LAVA)) { + landMovement(ctx); + } else { + lavaMovement(ctx, fluidHeight.rightDouble()); + } + } + case EMPTY -> landMovement(ctx); + } + } + + /** + * Adds velocity of all colliding fluids to the vehicle, and returns the height of the fluid to use for movement. + * + * @param ctx context + * @return type and height of fluid to use for movement + */ + protected ObjectDoublePair updateFluidMovement(VehicleContext ctx) { + BoundingBox box = boundingBox.clone(); + box.expand(-0.001); + + Vector3d min = box.getMin(); + Vector3d max = box.getMax(); + + BlockPositionIterator iter = BlockPositionIterator.fromMinMax(min.getFloorX(), min.getFloorY(), min.getFloorZ(), max.getFloorX(), max.getFloorY(), max.getFloorZ()); + + double waterHeight = getFluidHeightAndApplyMovement(ctx, iter, Fluid.WATER, 0.014, min.getY()); + double lavaHeight = getFluidHeightAndApplyMovement(ctx, iter, Fluid.LAVA, vehicle.getSession().getDimensionType().ultrawarm() ? 0.007 : 0.007 / 3, min.getY()); + + // Apply upward motion if the vehicle is a Strider, and it is submerged in lava + if (lavaHeight > 0 && vehicle.getDefinition().entityType() == EntityType.STRIDER) { + Vector3i blockPos = ctx.centerPos().toInt(); + if (!CollisionManager.FLUID_COLLISION.isBelow(blockPos.getY(), boundingBox) || ctx.getBlock(blockPos.up()).is(Blocks.LAVA)) { + vehicle.setMotion(vehicle.getMotion().mul(0.5f).add(0, 0.05f, 0)); + } else { + vehicle.setOnGround(true); + } + } + + // Water movement has priority over lava movement + if (waterHeight > 0) { + return ObjectDoublePair.of(Fluid.WATER, waterHeight); + } + + if (lavaHeight > 0) { + return ObjectDoublePair.of(Fluid.LAVA, lavaHeight); + } + + return EMPTY_FLUID_PAIR; + } + + /** + * Calculates how deep the vehicle is in a fluid, and applies its velocity. + * + * @param ctx context + * @param iter iterator of colliding blocks + * @param fluid type of fluid + * @param speed multiplier for fluid motion + * @param minY minY of the bounding box used to check for fluid collision; not exactly the same as the vehicle's bounding box + * @return height of fluid compared to minY + */ + protected double getFluidHeightAndApplyMovement(VehicleContext ctx, BlockPositionIterator iter, Fluid fluid, double speed, double minY) { + Vector3d totalVelocity = Vector3d.ZERO; + double maxFluidHeight = 0; + int fluidBlocks = 0; + + for (iter.reset(); iter.hasNext(); iter.next()) { + int blockId = ctx.getBlockId(iter); + if (BlockStateValues.getFluid(blockId) != fluid) { + continue; + } + + Vector3i blockPos = Vector3i.from(iter.getX(), iter.getY(), iter.getZ()); + float worldFluidHeight = getWorldFluidHeight(fluid, blockId); + + double vehicleFluidHeight = blockPos.getY() + worldFluidHeight - minY; + if (vehicleFluidHeight < 0) { + // Vehicle is not submerged in this fluid block + continue; + } + + // flowBlocked is only used when determining if a falling fluid should drag the vehicle downwards. + // If this block is not a falling fluid, set to true to avoid unnecessary checks. + boolean flowBlocked = worldFluidHeight != 1; + + Vector3d velocity = Vector3d.ZERO; + for (Direction direction : Direction.HORIZONTAL) { + Vector3i adjacentBlockPos = blockPos.add(direction.getUnitVector()); + int adjacentBlockId = ctx.getBlockId(adjacentBlockPos); + Fluid adjacentFluid = BlockStateValues.getFluid(adjacentBlockId); + + float fluidHeightDiff = 0; + if (adjacentFluid == fluid) { + fluidHeightDiff = getLogicalFluidHeight(fluid, blockId) - getLogicalFluidHeight(fluid, adjacentBlockId); + } else if (adjacentFluid == Fluid.EMPTY) { + // If the adjacent block is not a fluid and does not have collision, + // check if there is a fluid under it + BlockCollision adjacentBlockCollision = BlockUtils.getCollision(adjacentBlockId); + if (adjacentBlockCollision == null) { + float adjacentFluidHeight = getLogicalFluidHeight(fluid, ctx.getBlockId(adjacentBlockPos.add(Direction.DOWN.getUnitVector()))); + if (adjacentFluidHeight != -1) { // Only care about same type of fluid + fluidHeightDiff = getLogicalFluidHeight(fluid, blockId) - (adjacentFluidHeight - MAX_LOGICAL_FLUID_HEIGHT); + } + } else if (!flowBlocked) { + // No need to check if flow is already blocked from another direction, or if this isn't a falling fluid. + flowBlocked = isFlowBlocked(fluid, adjacentBlockId); + } + } + + if (fluidHeightDiff != 0) { + velocity = velocity.add(direction.getUnitVector().toDouble().mul(fluidHeightDiff)); + } + } + + if (worldFluidHeight == 1) { // If falling fluid + // If flow is not blocked, check if it is blocked for the fluid above + if (!flowBlocked) { + Vector3i blockPosUp = blockPos.up(); + for (Direction direction : Direction.HORIZONTAL) { + flowBlocked = isFlowBlocked(fluid, ctx.getBlockId(blockPosUp.add(direction.getUnitVector()))); + if (flowBlocked) { + break; + } + } + } + + if (flowBlocked) { + velocity = javaNormalize(velocity).add(0.0, -6.0, 0.0); + } + } + + velocity = javaNormalize(velocity); + + maxFluidHeight = Math.max(vehicleFluidHeight, maxFluidHeight); + if (maxFluidHeight < 0.4) { + velocity = velocity.mul(maxFluidHeight); + } + + totalVelocity = totalVelocity.add(velocity); + fluidBlocks++; + } + + if (!totalVelocity.equals(Vector3d.ZERO)) { + Vector3f motion = vehicle.getMotion(); + + totalVelocity = javaNormalize(totalVelocity.mul(1.0 / fluidBlocks)); + totalVelocity = totalVelocity.mul(speed); + + if (totalVelocity.length() < 0.0045 && Math.abs(motion.getX()) < MIN_VELOCITY && Math.abs(motion.getZ()) < MIN_VELOCITY) { + totalVelocity = javaNormalize(totalVelocity).mul(0.0045); + } + + vehicle.setMotion(motion.add(totalVelocity.toFloat())); + } + + return maxFluidHeight; + } + + /** + * Java edition returns the zero vector if the length of the input vector is less than 0.0001 + */ + protected Vector3d javaNormalize(Vector3d vec) { + double len = vec.length(); + return len < 1.0E-4 ? Vector3d.ZERO : Vector3d.from(vec.getX() / len, vec.getY() / len, vec.getZ() / len); + } + + protected float getWorldFluidHeight(Fluid fluidType, int blockId) { + return (float) switch (fluidType) { + case WATER -> BlockStateValues.getWaterHeight(blockId); + case LAVA -> BlockStateValues.getLavaHeight(blockId); + case EMPTY -> -1; + }; + } + + protected float getLogicalFluidHeight(Fluid fluidType, int blockId) { + return Math.min(getWorldFluidHeight(fluidType, blockId), MAX_LOGICAL_FLUID_HEIGHT); + } + + protected boolean isFlowBlocked(Fluid fluid, int adjacentBlockId) { + if (BlockState.of(adjacentBlockId).is(Blocks.ICE)) { + return false; + } + + if (BlockStateValues.getFluid(adjacentBlockId) == fluid) { + return false; + } + + // TODO: supposed to check if the opposite face of the block touching the fluid is solid, instead of SolidCollision + return BlockUtils.getCollision(adjacentBlockId) instanceof SolidCollision; + } + + protected void waterMovement(VehicleContext ctx) { + double gravity = getGravity(); + float drag = vehicle.getFlag(EntityFlag.SPRINTING) ? 0.9f : 0.8f; // 0.8f: getBaseMovementSpeedMultiplier + double originalY = ctx.centerPos().getY(); + boolean falling = vehicle.getMotion().getY() <= 0; + + // NOT IMPLEMENTED: depth strider and dolphins grace + + boolean horizontalCollision = travel(ctx, 0.02f); + + if (horizontalCollision && isClimbing(ctx)) { + vehicle.setMotion(Vector3f.from(vehicle.getMotion().getX(), 0.2f, vehicle.getMotion().getZ())); + } + + vehicle.setMotion(vehicle.getMotion().mul(drag, 0.8f, drag)); + vehicle.setMotion(getFluidGravity(gravity, falling)); + + if (horizontalCollision && shouldApplyFluidJumpBoost(ctx, originalY)) { + vehicle.setMotion(Vector3f.from(vehicle.getMotion().getX(), 0.3f, vehicle.getMotion().getZ())); + } + } + + protected void lavaMovement(VehicleContext ctx, double lavaHeight) { + double gravity = getGravity(); + double originalY = ctx.centerPos().getY(); + boolean falling = vehicle.getMotion().getY() <= 0; + + boolean horizontalCollision = travel(ctx, 0.02f); + + if (lavaHeight <= (boundingBox.getSizeY() * 0.85 < 0.4 ? 0.0 : 0.4)) { // Swim height + vehicle.setMotion(vehicle.getMotion().mul(0.5f, 0.8f, 0.5f)); + vehicle.setMotion(getFluidGravity(gravity, falling)); + } else { + vehicle.setMotion(vehicle.getMotion().mul(0.5f)); + } + + vehicle.setMotion(vehicle.getMotion().down((float) (gravity / 4.0))); + + if (horizontalCollision && shouldApplyFluidJumpBoost(ctx, originalY)) { + vehicle.setMotion(Vector3f.from(vehicle.getMotion().getX(), 0.3f, vehicle.getMotion().getZ())); + } + } + + protected void landMovement(VehicleContext ctx) { + double gravity = getGravity(); + float slipperiness = BlockStateValues.getSlipperiness(getVelocityBlock(ctx)); + float drag = vehicle.isOnGround() ? 0.91f * slipperiness : 0.91f; + float speed = vehicle.getVehicleSpeed() * (vehicle.isOnGround() ? BASE_SLIPPERINESS_CUBED / (slipperiness * slipperiness * slipperiness) : 0.1f); + + boolean horizontalCollision = travel(ctx, speed); + + if (isClimbing(ctx)) { + Vector3f motion = vehicle.getMotion(); + vehicle.setMotion( + Vector3f.from( + MathUtils.clamp(motion.getX(), -0.15f, 0.15f), + horizontalCollision ? 0.2f : Math.max(motion.getY(), -0.15f), + MathUtils.clamp(motion.getZ(), -0.15f, 0.15f) + ) + ); + // NOT IMPLEMENTED: climbing in powdered snow + } + + if (effectLevitation > 0) { + vehicle.setMotion(vehicle.getMotion().up((0.05f * effectLevitation - vehicle.getMotion().getY()) * 0.2f)); + } else { + vehicle.setMotion(vehicle.getMotion().down((float) gravity)); + // NOT IMPLEMENTED: slow fall when in unloaded chunk + } + + vehicle.setMotion(vehicle.getMotion().mul(drag, 0.98f, drag)); + } + + protected boolean shouldApplyFluidJumpBoost(VehicleContext ctx, double originalY) { + BoundingBox box = boundingBox.clone(); + box.translate(vehicle.getMotion().toDouble().up(0.6f - ctx.centerPos().getY() + originalY)); + box.expand(-1.0E-7); + + BlockPositionIterator iter = vehicle.getSession().getCollisionManager().collidableBlocksIterator(box); + for (iter.reset(); iter.hasNext(); iter.next()) { + int blockId = ctx.getBlockId(iter); + + // Also check for fluids + BlockCollision blockCollision = BlockUtils.getCollision(blockId); + if (blockCollision == null && BlockStateValues.getFluid(blockId) != Fluid.EMPTY) { + blockCollision = CollisionManager.SOLID_COLLISION; + } + + if (blockCollision != null && blockCollision.checkIntersection(iter.getX(), iter.getY(), iter.getZ(), box)) { + return false; + } + } + + return true; + } + + protected Vector3f getFluidGravity(double gravity, boolean falling) { + Vector3f motion = vehicle.getMotion(); + if (gravity != 0 && !vehicle.getFlag(EntityFlag.SPRINTING)) { + float newY = (float) (motion.getY() - gravity / 16); + if (falling && Math.abs(motion.getY() - 0.005f) >= MIN_VELOCITY && Math.abs(newY) < MIN_VELOCITY) { + newY = -MIN_VELOCITY; + } + return Vector3f.from(motion.getX(), newY, motion.getZ()); + } + return motion; + } + + /** + * Check if any blocks the vehicle is colliding with should multiply movement. (Cobweb, powder snow, berry bush) + *

    + * This is different from the speed factor of a block the vehicle is standing on, such as soul sand. + * + * @param ctx context + * @return the multiplier + */ + protected @Nullable Vector3f getBlockMovementMultiplier(VehicleContext ctx) { + BoundingBox box = boundingBox.clone(); + box.expand(-1.0E-7); + + Vector3i min = box.getMin().toInt(); + Vector3i max = box.getMax().toInt(); + + // Iterate xyz backwards + // Minecraft iterates forwards but only the last multiplier affects movement + for (int x = max.getX(); x >= min.getX(); x--) { + for (int y = max.getY(); y >= min.getY(); y--) { + for (int z = max.getZ(); z >= min.getZ(); z--) { + Block block = ctx.getBlock(x, y, z).block(); + Vector3f multiplier = null; + + if (block == Blocks.COBWEB) { + if (effectWeaving) { + multiplier = Vector3f.from(0.5, 0.25, 0.5); + } else { + multiplier = Vector3f.from(0.25, 0.05f, 0.25); + } + } else if (block == Blocks.POWDER_SNOW) { + multiplier = Vector3f.from(0.9f, 1.5, 0.9f); + } else if (block == Blocks.SWEET_BERRY_BUSH) { + multiplier = Vector3f.from(0.8f, 0.75, 0.8f); + } + + if (multiplier != null) { + return multiplier; + } + } + } + } + + return null; + } + + protected void applyBlockCollisionEffects(VehicleContext ctx) { + BoundingBox box = boundingBox.clone(); + box.expand(-1.0E-7); + + Vector3i min = box.getMin().toInt(); + Vector3i max = box.getMax().toInt(); + + BlockPositionIterator iter = BlockPositionIterator.fromMinMax(min.getX(), min.getY(), min.getZ(), max.getX(), max.getY(), max.getZ()); + for (iter.reset(); iter.hasNext(); iter.next()) { + BlockState blockState = ctx.getBlock(iter); + + if (blockState.is(Blocks.HONEY_BLOCK)) { + onHoneyBlockCollision(); + } else if (blockState.is(Blocks.BUBBLE_COLUMN)) { + onBubbleColumnCollision(blockState.getValue(Properties.DRAG)); + } + } + } + + protected void onHoneyBlockCollision() { + if (vehicle.isOnGround() || vehicle.getMotion().getY() >= -0.08f) { + return; + } + + // NOT IMPLEMENTED: don't slide if inside the honey block + Vector3f motion = vehicle.getMotion(); + float mul = motion.getY() < -0.13f ? -0.05f / motion.getY() : 1; + vehicle.setMotion(Vector3f.from(motion.getX() * mul, -0.05f, motion.getZ() * mul)); + } + + protected void onBubbleColumnCollision(boolean drag) { + Vector3f motion = vehicle.getMotion(); + vehicle.setMotion(Vector3f.from( + motion.getX(), + drag ? Math.max(-0.3f, motion.getY() - 0.03f) : Math.min(0.7f, motion.getY() + 0.06f), + motion.getZ() + )); + } + + /** + * Calculates the next position of the vehicle while checking for collision and adjusting velocity. + * + * @return true if there was a horizontal collision + */ + protected boolean travel(VehicleContext ctx, float speed) { + Vector3f motion = vehicle.getMotion(); + + // Java only does this client side + motion = motion.mul(0.98f); + + motion = Vector3f.from( + Math.abs(motion.getX()) < MIN_VELOCITY ? 0 : motion.getX(), + Math.abs(motion.getY()) < MIN_VELOCITY ? 0 : motion.getY(), + Math.abs(motion.getZ()) < MIN_VELOCITY ? 0 : motion.getZ() + ); + + // !isImmobile + if (vehicle.isAlive()) { + motion = motion.add(getInputVelocity(ctx, speed)); + } + + Vector3f movementMultiplier = getBlockMovementMultiplier(ctx); + if (movementMultiplier != null) { + motion = motion.mul(movementMultiplier); + } + + // Check world border before blocks + Vector3d correctedMovement = vehicle.getSession().getWorldBorder().correctMovement(boundingBox, motion.toDouble()); + correctedMovement = vehicle.getSession().getCollisionManager().correctMovement( + correctedMovement, boundingBox, vehicle.isOnGround(), this.stepHeight, true, vehicle.canWalkOnLava() + ); + + boundingBox.translate(correctedMovement); + ctx.loadSurroundingBlocks(); // Context must be reloaded after vehicle is moved + + // Non-zero values indicate a collision on that axis + Vector3d moveDiff = motion.toDouble().sub(correctedMovement); + + vehicle.setOnGround(moveDiff.getY() != 0 && motion.getY() < 0); + boolean horizontalCollision = moveDiff.getX() != 0 || moveDiff.getZ() != 0; + + boolean bounced = false; + if (vehicle.isOnGround()) { + Block landingBlock = getLandingBlock(ctx).block(); + + if (landingBlock == Blocks.SLIME_BLOCK) { + motion = Vector3f.from(motion.getX(), -motion.getY(), motion.getZ()); + bounced = true; + + // Slow horizontal movement + float absY = Math.abs(motion.getY()); + if (absY < 0.1f) { + float mul = 0.4f + absY * 0.2f; + motion = motion.mul(mul, 1.0f, mul); + } + } else if (landingBlock instanceof BedBlock) { + motion = Vector3f.from(motion.getX(), -motion.getY() * 0.66f, motion.getZ()); + bounced = true; + } + } + + // Set motion to 0 if a movement multiplier was used, else set to 0 on each axis with a collision + if (movementMultiplier != null) { + motion = Vector3f.ZERO; + } else { + motion = motion.mul( + moveDiff.getX() == 0 ? 1 : 0, + moveDiff.getY() == 0 || bounced ? 1 : 0, + moveDiff.getZ() == 0 ? 1 : 0 + ); + } + + // Send the new position to the bedrock client and java server + moveVehicle(ctx.centerPos()); + vehicle.setMotion(motion); + + applyBlockCollisionEffects(ctx); + + float velocityMultiplier = getVelocityMultiplier(ctx); + vehicle.setMotion(vehicle.getMotion().mul(velocityMultiplier, 1.0f, velocityMultiplier)); + + return horizontalCollision; + } + + protected boolean isClimbing(VehicleContext ctx) { + if (!vehicle.canClimb()) { + return false; + } + + BlockState blockState = ctx.centerBlock(); + if (vehicle.getSession().getTagCache().is(BlockTag.CLIMBABLE, blockState.block())) { + return true; + } + + // Check if the vehicle is in an open trapdoor with a ladder of the same direction under it + if (blockState.block() instanceof TrapDoorBlock && blockState.getValue(Properties.OPEN)) { + BlockState ladderState = ctx.getBlock(ctx.centerPos().toInt().down()); + return ladderState.is(Blocks.LADDER) && + ladderState.getValue(Properties.HORIZONTAL_FACING) == blockState.getValue(Properties.HORIZONTAL_FACING); + } + + return false; + } + + /** + * Translates the player's input into velocity. + * + * @param ctx context + * @param speed multiplier for input + * @return velocity + */ + protected Vector3f getInputVelocity(VehicleContext ctx, float speed) { + Vector2f input = vehicle.getSession().getPlayerEntity().getVehicleInput(); + input = input.mul(0.98f); + input = vehicle.getAdjustedInput(input); + input = normalizeInput(input); + input = input.mul(speed); + + // Match player rotation + float yaw = vehicle.getSession().getPlayerEntity().getYaw(); + float sin = TrigMath.sin(yaw * TrigMath.DEG_TO_RAD); + float cos = TrigMath.cos(yaw * TrigMath.DEG_TO_RAD); + return Vector3f.from(input.getX() * cos - input.getY() * sin, 0, input.getY() * cos + input.getX() * sin); + } + + protected Vector2f normalizeInput(Vector2f input) { + float lenSquared = input.lengthSquared(); + if (lenSquared < 1.0E-7) { + return Vector2f.ZERO; + } else if (lenSquared > 1.0) { + return input.normalize(); + } + return input; + } + + /** + * Gets the rotation to use for the vehicle. This is based on the player's head rotation. + */ + protected Vector2f getVehicleRotation() { + LivingEntity player = vehicle.getSession().getPlayerEntity(); + return Vector2f.from(player.getYaw(), player.getPitch() * 0.5f); + } + + /** + * Sets the new position for the vehicle and sends packets to both the java server and bedrock client. + *

    + * This also updates the session's last vehicle move timestamp. + * @param javaPos the new java position of the vehicle + */ + protected void moveVehicle(Vector3d javaPos) { + Vector3f bedrockPos = javaPos.toFloat(); + Vector2f rotation = getVehicleRotation(); + + MoveEntityDeltaPacket moveEntityDeltaPacket = new MoveEntityDeltaPacket(); + moveEntityDeltaPacket.setRuntimeEntityId(vehicle.getGeyserId()); + + if (vehicle.isOnGround()) { + moveEntityDeltaPacket.getFlags().add(MoveEntityDeltaPacket.Flag.ON_GROUND); + } + + if (vehicle.getPosition().getX() != bedrockPos.getX()) { + moveEntityDeltaPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_X); + moveEntityDeltaPacket.setX(bedrockPos.getX()); + } + if (vehicle.getPosition().getY() != bedrockPos.getY()) { + moveEntityDeltaPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_Y); + moveEntityDeltaPacket.setY(bedrockPos.getY()); + } + if (vehicle.getPosition().getZ() != bedrockPos.getZ()) { + moveEntityDeltaPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_Z); + moveEntityDeltaPacket.setZ(bedrockPos.getZ()); + } + vehicle.setPosition(bedrockPos); + + if (vehicle.getYaw() != rotation.getX()) { + moveEntityDeltaPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_YAW); + moveEntityDeltaPacket.setYaw(rotation.getX()); + vehicle.setYaw(rotation.getX()); + } + if (vehicle.getPitch() != rotation.getY()) { + moveEntityDeltaPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_PITCH); + moveEntityDeltaPacket.setPitch(rotation.getY()); + vehicle.setPitch(rotation.getY()); + } + if (vehicle.getHeadYaw() != rotation.getX()) { // Same as yaw + moveEntityDeltaPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_HEAD_YAW); + moveEntityDeltaPacket.setHeadYaw(rotation.getX()); + vehicle.setHeadYaw(rotation.getX()); + } + + if (!moveEntityDeltaPacket.getFlags().isEmpty()) { + vehicle.getSession().sendUpstreamPacket(moveEntityDeltaPacket); + } + + ServerboundMoveVehiclePacket moveVehiclePacket = new ServerboundMoveVehiclePacket(javaPos.getX(), javaPos.getY(), javaPos.getZ(), rotation.getX(), rotation.getY()); + vehicle.getSession().sendDownstreamPacket(moveVehiclePacket); + vehicle.getSession().setLastVehicleMoveTimestamp(System.currentTimeMillis()); + } + + protected double getGravity() { + if (!vehicle.getFlag(EntityFlag.HAS_GRAVITY)) { + return 0; + } + + if (vehicle.getMotion().getY() <= 0 && effectSlowFalling) { + return Math.min(0.01, this.gravity); + } + + return this.gravity; + } + + /** + * Finds the position of the main block supporting the vehicle. + * Used when determining slipperiness, speed, etc. + *

    + * Should use {@link VehicleContext#supportingBlockPos()}, instead of calling this directly. + * + * @param ctx context + * @return position of the main block supporting this entity + */ + private @Nullable Vector3i getSupportingBlockPos(VehicleContext ctx) { + Vector3i result = null; + + if (vehicle.isOnGround()) { + BoundingBox box = boundingBox.clone(); + box.extend(0, -1.0E-6, 0); // Extend slightly down + + Vector3i min = box.getMin().toInt(); + Vector3i max = box.getMax().toInt(); + + // Use minY as maxY + BlockPositionIterator iter = BlockPositionIterator.fromMinMax(min.getX(), min.getY(), min.getZ(), max.getX(), min.getY(), max.getZ()); + + double minDistance = Double.MAX_VALUE; + for (iter.reset(); iter.hasNext(); iter.next()) { + Vector3i blockPos = Vector3i.from(iter.getX(), iter.getY(), iter.getZ()); + int blockId = ctx.getBlockId(iter); + + BlockCollision blockCollision; + if (vehicle.canWalkOnLava()) { + blockCollision = vehicle.getSession().getCollisionManager().getCollisionLavaWalking(blockId, blockPos.getY(), boundingBox); + } else { + blockCollision = BlockUtils.getCollision(blockId); + } + + if (blockCollision != null && blockCollision.checkIntersection(blockPos, box)) { + double distance = ctx.centerPos().distanceSquared(blockPos.toDouble().add(0.5f, 0.5f, 0.5f)); + if (distance <= minDistance) { + minDistance = distance; + result = blockPos; + } + } + } + } + + return result; + } + + /** + * Returns the block that is x amount of blocks under the main supporting block. + */ + protected BlockState getBlockUnderSupport(VehicleContext ctx, float dist) { + Vector3i supportingBlockPos = ctx.supportingBlockPos(); + + Vector3i blockPos; + if (supportingBlockPos != null) { + blockPos = Vector3i.from(supportingBlockPos.getX(), Math.floor(ctx.centerPos().getY() - dist), supportingBlockPos.getZ()); + } else { + blockPos = ctx.centerPos().sub(0, dist, 0).toInt(); + } + + return ctx.getBlock(blockPos); + } + + /** + * The block to use when determining if the vehicle should bounce after landing. Currently just slime and bed blocks. + */ + protected BlockState getLandingBlock(VehicleContext ctx) { + return getBlockUnderSupport(ctx, 0.2f); + } + + /** + * The block to use when calculating slipperiness and speed. If on a slab, this will be the block under the slab. + */ + protected BlockState getVelocityBlock(VehicleContext ctx) { + return getBlockUnderSupport(ctx, 0.500001f); + } + + protected float getVelocityMultiplier(VehicleContext ctx) { + Block block = ctx.centerBlock().block(); + if (block == Blocks.WATER || block == Blocks.BUBBLE_COLUMN) { + return 1.0f; + } + + if (block == Blocks.SOUL_SAND || block == Blocks.HONEY_BLOCK) { + return 0.4f; + } + + block = getVelocityBlock(ctx).block(); + if (block == Blocks.SOUL_SAND || block == Blocks.HONEY_BLOCK) { + return 0.4f; + } + + return 1.0f; + } + + protected float getJumpVelocityMultiplier(VehicleContext ctx) { + Block block = ctx.centerBlock().block(); + if (block == Blocks.HONEY_BLOCK) { + return 0.5f; + } + + block = getVelocityBlock(ctx).block(); + if (block == Blocks.HONEY_BLOCK) { + return 0.5f; + } + + return 1.0f; + } + + protected class VehicleContext { + private Vector3d centerPos; + private Vector3d cachePos; + private BlockState centerBlock; + private Vector3i supportingBlockPos; + private BlockPositionIterator blockIter; + private int[] blocks; + + /** + * Cache frequently used data and blocks used in movement calculations. + *

    + * Can be called multiple times, and must be called at least once before using the VehicleContext. + */ + protected void loadSurroundingBlocks() { + this.centerPos = boundingBox.getBottomCenter(); + + // Reuse block cache if vehicle moved less than 1 block + if (this.cachePos == null || this.cachePos.distanceSquared(this.centerPos) > 1) { + BoundingBox box = boundingBox.clone(); + box.expand(2); + + Vector3i min = box.getMin().toInt(); + Vector3i max = box.getMax().toInt(); + this.blockIter = BlockPositionIterator.fromMinMax(min.getX(), min.getY(), min.getZ(), max.getX(), max.getY(), max.getZ()); + this.blocks = vehicle.getSession().getGeyser().getWorldManager().getBlocksAt(vehicle.getSession(), this.blockIter); + + this.cachePos = this.centerPos; + } + + this.centerBlock = getBlock(this.centerPos.toInt()); + this.supportingBlockPos = null; + } + + protected Vector3d centerPos() { + return this.centerPos; + } + + protected BlockState centerBlock() { + return this.centerBlock; + } + + protected Vector3i supportingBlockPos() { + if (this.supportingBlockPos == null) { + this.supportingBlockPos = getSupportingBlockPos(this); + } + + return this.supportingBlockPos; + } + + protected int getBlockId(int x, int y, int z) { + int index = this.blockIter.getIndex(x, y, z); + if (index == -1) { + vehicle.getSession().getGeyser().getLogger().debug("[client-vehicle] Block cache miss"); + return vehicle.getSession().getGeyser().getWorldManager().getBlockAt(vehicle.getSession(), x, y, z); + } + + return blocks[index]; + } + + protected int getBlockId(Vector3i pos) { + return getBlockId(pos.getX(), pos.getY(), pos.getZ()); + } + + protected int getBlockId(BlockPositionIterator iter) { + return getBlockId(iter.getX(), iter.getY(), iter.getZ()); + } + + protected BlockState getBlock(int x, int y, int z) { + return BlockState.of(getBlockId(x, y, z)); + } + + protected BlockState getBlock(Vector3i pos) { + return BlockState.of(getBlockId(pos.getX(), pos.getY(), pos.getZ())); + } + + protected BlockState getBlock(BlockPositionIterator iter) { + return BlockState.of(getBlockId(iter.getX(), iter.getY(), iter.getZ())); + } + } +} 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 c3756d663..3ea9cd112 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/PlayerInventory.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/PlayerInventory.java @@ -62,6 +62,16 @@ public class PlayerInventory extends Inventory { cursor = newCursor; } + /** + * Checks if the player is holding the specified item in either hand + * + * @param item The item to look for + * @return If the player is holding the item in either hand + */ + public boolean isHolding(@NonNull Item item) { + return getItemInHand().asItem() == item || getOffhand().asItem() == item; + } + public GeyserItemStack getItemInHand(@NonNull Hand hand) { return hand == Hand.OFF_HAND ? getOffhand() : getItemInHand(); } 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 475a3e588..a8a711cc2 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 @@ -43,6 +43,7 @@ public class StoredItemMappings { private final ItemMapping banner; private final ItemMapping barrier; private final ItemMapping bow; + private final ItemMapping carrotOnAStick; private final ItemMapping compass; private final ItemMapping crossbow; private final ItemMapping egg; @@ -52,6 +53,7 @@ public class StoredItemMappings { private final ItemMapping shield; private final ItemMapping totem; private final ItemMapping upgradeTemplate; + private final ItemMapping warpedFungusOnAStick; private final ItemMapping wheat; private final ItemMapping writableBook; private final ItemMapping writtenBook; @@ -60,6 +62,7 @@ public class StoredItemMappings { 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.carrotOnAStick = load(itemMappings, Items.CARROT_ON_A_STICK); this.compass = load(itemMappings, Items.COMPASS); this.crossbow = load(itemMappings, Items.CROSSBOW); this.egg = load(itemMappings, Items.EGG); @@ -69,6 +72,7 @@ public class StoredItemMappings { this.shield = load(itemMappings, Items.SHIELD); this.totem = load(itemMappings, Items.TOTEM_OF_UNDYING); this.upgradeTemplate = load(itemMappings, Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE); + this.warpedFungusOnAStick = load(itemMappings, Items.WARPED_FUNGUS_ON_A_STICK); this.wheat = load(itemMappings, Items.WHEAT); this.writableBook = load(itemMappings, Items.WRITABLE_BOOK); this.writtenBook = load(itemMappings, Items.WRITTEN_BOOK); 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 0ca428830..50589851b 100644 --- a/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java +++ b/core/src/main/java/org/geysermc/geyser/level/JavaDimension.java @@ -34,11 +34,13 @@ import org.geysermc.geyser.util.DimensionUtils; * Represents the information we store from the current Java dimension * @param piglinSafe Whether piglins and hoglins are safe from conversion in this dimension. * This controls if they have the shaking effect applied in the dimension. + * @param ultrawarm If this dimension is ultrawarm. + * Used when calculating movement in lava for client-side vehicles. * @param bedrockId the Bedrock dimension ID of this dimension. * As a Java dimension can be null in some login cases (e.g. GeyserConnect), make sure the player * is logged in before utilizing this field. */ -public record JavaDimension(int minY, int maxY, boolean piglinSafe, double worldCoordinateScale, int bedrockId, boolean isNetherLike) { +public record JavaDimension(int minY, int maxY, boolean piglinSafe, boolean ultrawarm, double worldCoordinateScale, int bedrockId, boolean isNetherLike) { public static JavaDimension read(RegistryEntryContext entry) { NbtMap dimension = entry.data(); @@ -48,6 +50,8 @@ public record JavaDimension(int minY, int maxY, boolean piglinSafe, double world // Set if piglins/hoglins should shake boolean piglinSafe = dimension.getBoolean("piglin_safe"); + // Entities in lava move faster in ultrawarm dimensions + boolean ultrawarm = dimension.getBoolean("ultrawarm"); // Load world coordinate scale for the world border double coordinateScale = dimension.getNumber("coordinate_scale").doubleValue(); // FIXME see if we can change this in the NBT library itself. @@ -67,6 +71,6 @@ public record JavaDimension(int minY, int maxY, boolean piglinSafe, double world isNetherLike = DimensionUtils.NETHER_IDENTIFIER.equals(effects); } - return new JavaDimension(minY, maxY, piglinSafe, coordinateScale, bedrockId, isNetherLike); + return new JavaDimension(minY, maxY, piglinSafe, ultrawarm, coordinateScale, bedrockId, isNetherLike); } } 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 01e95fc7a..36e437026 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 @@ -36,7 +36,7 @@ import org.geysermc.geyser.registry.BlockRegistries; * Used for block entities if the Java block state contains Bedrock block information. */ public final class BlockStateValues { - public static final int NUM_WATER_LEVELS = 9; + public static final int NUM_FLUID_LEVELS = 9; /** * Checks if a block sticks to other blocks @@ -99,6 +99,25 @@ public final class BlockStateValues { }; } + /** + * Get the type of fluid from the block state, including waterlogged blocks. + * + * @param state BlockState of the block + * @return The type of fluid + */ + public static Fluid getFluid(int state) { + BlockState blockState = BlockState.of(state); + if (blockState.is(Blocks.WATER) || BlockRegistries.WATERLOGGED.get().get(state)) { + return Fluid.WATER; + } + + if (blockState.is(Blocks.LAVA)) { + return Fluid.LAVA; + } + + return Fluid.EMPTY; + } + /** * Get the level of water from the block state. * @@ -127,7 +146,7 @@ public final class BlockStateValues { waterLevel = 0; } if (waterLevel >= 0) { - double waterHeight = 1 - (waterLevel + 1) / ((double) NUM_WATER_LEVELS); + double waterHeight = 1 - (waterLevel + 1) / ((double) NUM_FLUID_LEVELS); // Falling water is a full block if (waterLevel >= 8) { waterHeight = 1; @@ -137,6 +156,39 @@ public final class BlockStateValues { return -1; } + /** + * Get the level of lava from the block state. + * + * @param state BlockState of the block + * @return The lava level or -1 if the block isn't lava + */ + public static int getLavaLevel(int state) { + BlockState blockState = BlockState.of(state); + if (!blockState.is(Blocks.LAVA)) { + return -1; + } + return blockState.getValue(Properties.LEVEL); + } + + /** + * Get the height of lava from the block state + * + * @param state BlockState of the block + * @return The lava height or -1 if the block does not contain lava + */ + public static double getLavaHeight(int state) { + int lavaLevel = BlockStateValues.getLavaLevel(state); + if (lavaLevel >= 0) { + double lavaHeight = 1 - (lavaLevel + 1) / ((double) NUM_FLUID_LEVELS); + // Falling lava is a full block + if (lavaLevel >= 8) { + lavaHeight = 1; + } + return lavaHeight; + } + return -1; + } + /** * Get the slipperiness of a block. * This is used in ItemEntity to calculate the friction on an item as it slides across the ground diff --git a/core/src/main/java/org/geysermc/geyser/level/block/Fluid.java b/core/src/main/java/org/geysermc/geyser/level/block/Fluid.java new file mode 100644 index 000000000..a9693bbf4 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/level/block/Fluid.java @@ -0,0 +1,32 @@ +/* + * 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; + +public enum Fluid { + WATER, + LAVA, + EMPTY +} 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 b1a93d8ee..395467c02 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 @@ -33,6 +33,8 @@ import org.cloudburstmc.math.vector.Vector3d; @Data @AllArgsConstructor public class BoundingBox implements Cloneable { + private static final double EPSILON = 1.0E-7; + private double middleX; private double middleY; private double middleZ; @@ -57,10 +59,24 @@ public class BoundingBox implements Cloneable { sizeZ += Math.abs(z); } + public void expand(double x, double y, double z) { + sizeX += x; + sizeY += y; + sizeZ += z; + } + + public void translate(Vector3d translate) { + translate(translate.getX(), translate.getY(), translate.getZ()); + } + public void extend(Vector3d extend) { extend(extend.getX(), extend.getY(), extend.getZ()); } + public void expand(double expand) { + expand(expand, expand, expand); + } + public boolean checkIntersection(double offsetX, double offsetY, double offsetZ, BoundingBox otherBox) { return (Math.abs((middleX + offsetX) - otherBox.getMiddleX()) * 2 < (sizeX + otherBox.getSizeX())) && (Math.abs((middleY + offsetY) - otherBox.getMiddleY()) * 2 < (sizeY + otherBox.getSizeY())) && @@ -78,6 +94,14 @@ public class BoundingBox implements Cloneable { return Vector3d.from(x, y, z); } + public double getMin(Axis axis) { + return switch (axis) { + case X -> middleX - sizeX / 2; + case Y -> middleY - sizeY / 2; + case Z -> middleZ - sizeZ / 2; + }; + } + public Vector3d getMax() { double x = middleX + sizeX / 2; double y = middleY + sizeY / 2; @@ -85,15 +109,23 @@ public class BoundingBox implements Cloneable { return Vector3d.from(x, y, z); } + public double getMax(Axis axis) { + return switch (axis) { + case X -> middleX + sizeX / 2; + case Y -> middleY + sizeY / 2; + case Z -> middleZ + sizeZ / 2; + }; + } + public Vector3d getBottomCenter() { return Vector3d.from(middleX, middleY - sizeY / 2, middleZ); } private boolean checkOverlapInAxis(double xOffset, double yOffset, double zOffset, BoundingBox otherBox, Axis axis) { return switch (axis) { - case X -> Math.abs((middleX + xOffset) - otherBox.getMiddleX()) * 2 < (sizeX + otherBox.getSizeX()); - case Y -> Math.abs((middleY + yOffset) - otherBox.getMiddleY()) * 2 < (sizeY + otherBox.getSizeY()); - case Z -> Math.abs((middleZ + zOffset) - otherBox.getMiddleZ()) * 2 < (sizeZ + otherBox.getSizeZ()); + case X -> (sizeX + otherBox.getSizeX()) - Math.abs((middleX + xOffset) - otherBox.getMiddleX()) * 2 > EPSILON; + case Y -> (sizeY + otherBox.getSizeY()) - Math.abs((middleY + yOffset) - otherBox.getMiddleY()) * 2 > EPSILON; + case Z -> (sizeZ + otherBox.getSizeZ()) - Math.abs((middleZ + zOffset) - otherBox.getMiddleZ()) * 2 > EPSILON; }; } 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 2be4e7a38..a0fb312b4 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 @@ -38,6 +38,7 @@ import org.geysermc.erosion.util.BlockPositionIterator; import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.player.PlayerEntity; +import org.geysermc.geyser.entity.vehicle.ClientVehicle; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.level.block.property.Properties; @@ -45,7 +46,9 @@ import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.PistonCache; import org.geysermc.geyser.translator.collision.BlockCollision; +import org.geysermc.geyser.translator.collision.OtherCollision; import org.geysermc.geyser.translator.collision.ScaffoldingCollision; +import org.geysermc.geyser.translator.collision.SolidCollision; import org.geysermc.geyser.util.BlockUtils; import java.text.DecimalFormat; @@ -53,6 +56,8 @@ import java.text.DecimalFormatSymbols; import java.util.Locale; public class CollisionManager { + public static final BlockCollision SOLID_COLLISION = new SolidCollision(null); + public static final BlockCollision FLUID_COLLISION = new OtherCollision(new BoundingBox[]{new BoundingBox(0.5, 0.25, 0.5, 1, 0.5, 1)}); private final GeyserSession session; @@ -128,6 +133,21 @@ public class CollisionManager { playerBoundingBox.setSizeY(playerHeight); } + /** + * Gets the bounding box to use for player movement. + *

    + * This will return either the bounding box of a {@link ClientVehicle}, or the player's own bounding box. + * + * @return the bounding box to use for movement calculations + */ + public BoundingBox getActiveBoundingBox() { + if (session.getPlayerEntity().getVehicle() instanceof ClientVehicle clientVehicle && clientVehicle.isClientControlled()) { + return clientVehicle.getVehicleComponent().getBoundingBox(); + } + + return playerBoundingBox; + } + /** * Adjust the Bedrock position before sending to the Java server to account for inaccuracies in movement between * the two versions. Will also send corrected movement packets back to Bedrock if they collide with pistons. @@ -150,6 +170,15 @@ public class CollisionManager { Vector3d position = Vector3d.from(Double.parseDouble(Float.toString(bedrockPosition.getX())), javaY, Double.parseDouble(Float.toString(bedrockPosition.getZ()))); + // Don't correct position if controlling a vehicle + if (session.getPlayerEntity().getVehicle() instanceof ClientVehicle clientVehicle && clientVehicle.isClientControlled()) { + playerBoundingBox.setMiddleX(position.getX()); + playerBoundingBox.setMiddleY(position.getY() + playerBoundingBox.getSizeY() / 2); + playerBoundingBox.setMiddleZ(position.getZ()); + + return playerBoundingBox.getBottomCenter(); + } + Vector3d startingPos = playerBoundingBox.getBottomCenter(); Vector3d movement = position.sub(startingPos); Vector3d adjustedMovement = correctPlayerMovement(movement, false, teleported); @@ -173,7 +202,8 @@ public class CollisionManager { // Send corrected position to Bedrock if they differ by too much to prevent de-syncs if (onGround != newOnGround || movement.distanceSquared(adjustedMovement) > INCORRECT_MOVEMENT_THRESHOLD) { PlayerEntity playerEntity = session.getPlayerEntity(); - if (pistonCache.getPlayerMotion().equals(Vector3f.ZERO) && !pistonCache.isPlayerSlimeCollision()) { + // Client will dismount if on a vehicle + if (playerEntity.getVehicle() == null && pistonCache.getPlayerMotion().equals(Vector3f.ZERO) && !pistonCache.isPlayerSlimeCollision()) { playerEntity.moveAbsolute(position.toFloat(), playerEntity.getYaw(), playerEntity.getPitch(), playerEntity.getHeadYaw(), newOnGround, true); } } @@ -268,13 +298,13 @@ public class CollisionManager { if (teleported || (!checkWorld && session.getPistonCache().getPistons().isEmpty())) { // There is nothing to check return movement; } - return correctMovement(movement, playerBoundingBox, session.getPlayerEntity().isOnGround(), PLAYER_STEP_UP, checkWorld); + return correctMovement(movement, playerBoundingBox, session.getPlayerEntity().isOnGround(), PLAYER_STEP_UP, checkWorld, false); } - public Vector3d correctMovement(Vector3d movement, BoundingBox boundingBox, boolean onGround, double stepUp, boolean checkWorld) { + public Vector3d correctMovement(Vector3d movement, BoundingBox boundingBox, boolean onGround, double stepUp, boolean checkWorld, boolean walkOnLava) { Vector3d adjustedMovement = movement; if (!movement.equals(Vector3d.ZERO)) { - adjustedMovement = correctMovementForCollisions(movement, boundingBox, checkWorld); + adjustedMovement = correctMovementForCollisions(movement, boundingBox, checkWorld, walkOnLava); } boolean verticalCollision = adjustedMovement.getY() != movement.getY(); @@ -283,26 +313,27 @@ public class CollisionManager { onGround = onGround || (verticalCollision && falling); if (onGround && horizontalCollision) { Vector3d horizontalMovement = Vector3d.from(movement.getX(), 0, movement.getZ()); - Vector3d stepUpMovement = correctMovementForCollisions(horizontalMovement.up(stepUp), boundingBox, checkWorld); + Vector3d stepUpMovement = correctMovementForCollisions(horizontalMovement.up(stepUp), boundingBox, checkWorld, walkOnLava); BoundingBox stretchedBoundingBox = boundingBox.clone(); stretchedBoundingBox.extend(horizontalMovement); - double maxStepUp = correctMovementForCollisions(Vector3d.from(0, stepUp, 0), stretchedBoundingBox, checkWorld).getY(); + double maxStepUp = correctMovementForCollisions(Vector3d.from(0, stepUp, 0), stretchedBoundingBox, checkWorld, walkOnLava).getY(); if (maxStepUp < stepUp) { // The player collided with a block above them - boundingBox.translate(0, maxStepUp, 0); - Vector3d adjustedStepUpMovement = correctMovementForCollisions(horizontalMovement, boundingBox, checkWorld); - boundingBox.translate(0, -maxStepUp, 0); + BoundingBox stepUpBoundingBox = boundingBox.clone(); + stepUpBoundingBox.translate(0, maxStepUp, 0); + Vector3d adjustedStepUpMovement = correctMovementForCollisions(horizontalMovement, stepUpBoundingBox, checkWorld, walkOnLava); if (squaredHorizontalLength(adjustedStepUpMovement) > squaredHorizontalLength(stepUpMovement)) { stepUpMovement = adjustedStepUpMovement.up(maxStepUp); } } if (squaredHorizontalLength(stepUpMovement) > squaredHorizontalLength(adjustedMovement)) { - boundingBox.translate(stepUpMovement.getX(), stepUpMovement.getY(), stepUpMovement.getZ()); + BoundingBox stepUpBoundingBox = boundingBox.clone(); + stepUpBoundingBox.translate(stepUpMovement.getX(), stepUpMovement.getY(), stepUpMovement.getZ()); + // Apply the player's remaining vertical movement - double verticalMovement = correctMovementForCollisions(Vector3d.from(0, movement.getY() - stepUpMovement.getY(), 0), boundingBox, checkWorld).getY(); - boundingBox.translate(-stepUpMovement.getX(), -stepUpMovement.getY(), -stepUpMovement.getZ()); + double verticalMovement = correctMovementForCollisions(Vector3d.from(0, movement.getY() - stepUpMovement.getY(), 0), stepUpBoundingBox, checkWorld, walkOnLava).getY(); stepUpMovement = stepUpMovement.up(verticalMovement); adjustedMovement = stepUpMovement; @@ -315,43 +346,53 @@ public class CollisionManager { return vector.getX() * vector.getX() + vector.getZ() * vector.getZ(); } - private Vector3d correctMovementForCollisions(Vector3d movement, BoundingBox boundingBox, boolean checkWorld) { + private Vector3d correctMovementForCollisions(Vector3d movement, BoundingBox boundingBox, boolean checkWorld, boolean walkOnLava) { double movementX = movement.getX(); double movementY = movement.getY(); double movementZ = movement.getZ(); + // Position might change slightly due to floating point error + double originalX = boundingBox.getMiddleX(); + double originalY = boundingBox.getMiddleY(); + double originalZ = boundingBox.getMiddleZ(); + BoundingBox movementBoundingBox = boundingBox.clone(); movementBoundingBox.extend(movement); BlockPositionIterator iter = collidableBlocksIterator(movementBoundingBox); if (Math.abs(movementY) > CollisionManager.COLLISION_TOLERANCE) { - movementY = computeCollisionOffset(boundingBox, Axis.Y, movementY, iter, checkWorld); + movementY = computeCollisionOffset(boundingBox, Axis.Y, movementY, iter, checkWorld, walkOnLava); boundingBox.translate(0, movementY, 0); } boolean checkZFirst = Math.abs(movementZ) > Math.abs(movementX); if (checkZFirst && Math.abs(movementZ) > CollisionManager.COLLISION_TOLERANCE) { - movementZ = computeCollisionOffset(boundingBox, Axis.Z, movementZ, iter, checkWorld); + movementZ = computeCollisionOffset(boundingBox, Axis.Z, movementZ, iter, checkWorld, walkOnLava); boundingBox.translate(0, 0, movementZ); } if (Math.abs(movementX) > CollisionManager.COLLISION_TOLERANCE) { - movementX = computeCollisionOffset(boundingBox, Axis.X, movementX, iter, checkWorld); + movementX = computeCollisionOffset(boundingBox, Axis.X, movementX, iter, checkWorld, walkOnLava); boundingBox.translate(movementX, 0, 0); } if (!checkZFirst && Math.abs(movementZ) > CollisionManager.COLLISION_TOLERANCE) { - movementZ = computeCollisionOffset(boundingBox, Axis.Z, movementZ, iter, checkWorld); + movementZ = computeCollisionOffset(boundingBox, Axis.Z, movementZ, iter, checkWorld, walkOnLava); boundingBox.translate(0, 0, movementZ); } - boundingBox.translate(-movementX, -movementY, -movementZ); + boundingBox.setMiddleX(originalX); + boundingBox.setMiddleY(originalY); + boundingBox.setMiddleZ(originalZ); + return Vector3d.from(movementX, movementY, movementZ); } - private double computeCollisionOffset(BoundingBox boundingBox, Axis axis, double offset, BlockPositionIterator iter, boolean checkWorld) { + private double computeCollisionOffset(BoundingBox boundingBox, Axis axis, double offset, BlockPositionIterator iter, boolean checkWorld, boolean walkOnLava) { for (iter.reset(); iter.hasNext(); iter.next()) { int x = iter.getX(); int y = iter.getY(); int z = iter.getZ(); if (checkWorld) { - BlockCollision blockCollision = BlockUtils.getCollisionAt(session, x, y, z); + int blockId = session.getGeyser().getWorldManager().getBlockAt(session, x, y, z); + + BlockCollision blockCollision = walkOnLava ? getCollisionLavaWalking(blockId, y, boundingBox) : BlockUtils.getCollision(blockId); if (blockCollision != null && !(blockCollision instanceof ScaffoldingCollision)) { offset = blockCollision.computeCollisionOffset(x, y, z, boundingBox, axis, offset); } @@ -364,6 +405,16 @@ public class CollisionManager { return offset; } + /** + * @return the block collision appropriate for entities that can walk on lava (Strider) + */ + public BlockCollision getCollisionLavaWalking(int blockId, int blockY, BoundingBox boundingBox) { + if (BlockStateValues.getLavaLevel(blockId) == 0 && FLUID_COLLISION.isBelow(blockY, boundingBox)) { + return FLUID_COLLISION; + } + return BlockUtils.getCollision(blockId); + } + /** * @return true if the block located at the player's floor position plus 1 would intersect with the player, * were they not sneaking @@ -417,7 +468,7 @@ public class CollisionManager { double eyeY = playerBoundingBox.getMiddleY() - playerBoundingBox.getSizeY() / 2d + session.getEyeHeight(); double eyeZ = playerBoundingBox.getMiddleZ(); - eyeY -= 1 / ((double) BlockStateValues.NUM_WATER_LEVELS); // Subtract the height of one water layer + eyeY -= 1 / ((double) BlockStateValues.NUM_FLUID_LEVELS); // Subtract the height of one water layer int blockID = session.getGeyser().getWorldManager().getBlockAt(session, GenericMath.floor(eyeX), GenericMath.floor(eyeY), GenericMath.floor(eyeZ)); double waterHeight = BlockStateValues.getWaterHeight(blockID); 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 f14a46999..4821734f3 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 @@ -38,6 +38,7 @@ public enum Direction { EAST(4, Vector3i.UNIT_X, Axis.X, org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction.EAST); public static final Direction[] VALUES = values(); + public static final Direction[] HORIZONTAL = new Direction[]{Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST}; private final int reversedId; @Getter 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 9137c4756..607a58e0b 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.entity.type.Entity; import org.geysermc.geyser.entity.type.ItemFrameEntity; import org.geysermc.geyser.entity.type.Tickable; import org.geysermc.geyser.entity.type.player.SessionPlayerEntity; +import org.geysermc.geyser.entity.vehicle.ClientVehicle; import org.geysermc.geyser.erosion.AbstractGeyserboundPacketHandler; import org.geysermc.geyser.erosion.GeyserboundHandshakePacketHandler; import org.geysermc.geyser.impl.camera.CameraDefinitions; @@ -602,6 +603,19 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { */ private ScheduledFuture tickThread = null; + /** + * The number of ticks that have elapsed since the start of this session + */ + private int ticks; + + /** + * The world time in ticks according to the server + *

    + * Note: The TickingStatePacket is currently ignored. + */ + @Setter + private long worldTicks; + /** * Used to return the player to their original rotation after using an item in BedrockInventoryTransactionTranslator */ @@ -1261,6 +1275,10 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { isInWorldBorderWarningArea = false; } + Entity vehicle = playerEntity.getVehicle(); + if (vehicle instanceof ClientVehicle clientVehicle && vehicle.isValid()) { + clientVehicle.getVehicleComponent().tickVehicle(); + } for (Tickable entity : entityCache.getTickableEntities()) { entity.tick(); @@ -1296,6 +1314,9 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { } catch (Throwable throwable) { throwable.printStackTrace(); } + + ticks++; + worldTicks++; } public void setAuthenticationData(AuthData authData) { diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/PistonCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/PistonCache.java index d0a5bc094..dee4aa7cf 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/PistonCache.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/PistonCache.java @@ -33,7 +33,9 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; +import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.player.SessionPlayerEntity; +import org.geysermc.geyser.entity.vehicle.ClientVehicle; import org.geysermc.geyser.level.physics.Axis; import org.geysermc.geyser.level.physics.BoundingBox; import org.geysermc.geyser.session.GeyserSession; @@ -119,6 +121,12 @@ public class PistonCache { private void sendPlayerMovement() { if (!playerDisplacement.equals(Vector3d.ZERO) && playerMotion.equals(Vector3f.ZERO)) { SessionPlayerEntity playerEntity = session.getPlayerEntity(); + + Entity vehicle = playerEntity.getVehicle(); + if (vehicle instanceof ClientVehicle clientVehicle && clientVehicle.isClientControlled()) { + return; + } + boolean isOnGround = playerDisplacement.getY() > 0 || playerEntity.isOnGround(); Vector3d position = session.getCollisionManager().getPlayerBoundingBox().getBottomCenter(); playerEntity.moveAbsolute(position.toFloat(), playerEntity.getYaw(), playerEntity.getPitch(), playerEntity.getHeadYaw(), isOnGround, true); @@ -128,6 +136,13 @@ public class PistonCache { private void sendPlayerMotion() { if (!playerMotion.equals(Vector3f.ZERO)) { SessionPlayerEntity playerEntity = session.getPlayerEntity(); + + Entity vehicle = playerEntity.getVehicle(); + if (vehicle instanceof ClientVehicle clientVehicle && clientVehicle.isClientControlled()) { + vehicle.setMotion(playerMotion); + return; + } + playerEntity.setMotion(playerMotion); SetEntityMotionPacket setEntityMotionPacket = new SetEntityMotionPacket(); @@ -149,10 +164,15 @@ public class PistonCache { totalDisplacement = totalDisplacement.max(-0.51d, -0.51d, -0.51d).min(0.51d, 0.51d, 0.51d); Vector3d delta = totalDisplacement.sub(playerDisplacement); - // Check if the piston is pushing a player into collision - delta = session.getCollisionManager().correctPlayerMovement(delta, true, false); - session.getCollisionManager().getPlayerBoundingBox().translate(delta.getX(), delta.getY(), delta.getZ()); + // Check if the piston is pushing a player into collision + if (session.getPlayerEntity().getVehicle() instanceof ClientVehicle clientVehicle && clientVehicle.isClientControlled()) { + delta = clientVehicle.getVehicleComponent().correctMovement(delta); + clientVehicle.getVehicleComponent().moveRelative(delta); + } else { + delta = session.getCollisionManager().correctPlayerMovement(delta, true, false); + session.getCollisionManager().getPlayerBoundingBox().translate(delta.getX(), delta.getY(), delta.getZ()); + } playerDisplacement = totalDisplacement; } 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 8cb590f57..35579db13 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 @@ -28,6 +28,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.Vector3d; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; import org.cloudburstmc.protocol.bedrock.data.LevelEventType; @@ -36,8 +37,12 @@ import lombok.Getter; import lombok.Setter; import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.type.player.PlayerEntity; +import org.geysermc.geyser.level.physics.Axis; +import org.geysermc.geyser.level.physics.BoundingBox; import org.geysermc.geyser.session.GeyserSession; +import static org.geysermc.geyser.level.physics.CollisionManager.COLLISION_TOLERANCE; + public class WorldBorder { private static final double DEFAULT_WORLD_BORDER_SIZE = 5.9999968E7D; @@ -190,6 +195,53 @@ public class WorldBorder { return entityPosition.getX() > warningMinX && entityPosition.getX() < warningMaxX && entityPosition.getZ() > warningMinZ && entityPosition.getZ() < warningMaxZ; } + /** + * Adjusts the movement of an entity so that it does not cross the world border. + * + * @param boundingBox bounding box of the entity + * @param movement movement of the entity + * @return the corrected movement + */ + public Vector3d correctMovement(BoundingBox boundingBox, Vector3d movement) { + double correctedX; + if (movement.getX() < 0) { + correctedX = -limitMovement(-movement.getX(), boundingBox.getMin(Axis.X) - GenericMath.floor(minX)); + } else { + correctedX = limitMovement(movement.getX(), GenericMath.ceil(maxX) - boundingBox.getMax(Axis.X)); + } + + // Outside of border, don't adjust movement + if (Double.isNaN(correctedX)) { + return movement; + } + + double correctedZ; + if (movement.getZ() < 0) { + correctedZ = -limitMovement(-movement.getZ(), boundingBox.getMin(Axis.Z) - GenericMath.floor(minZ)); + } else { + correctedZ = limitMovement(movement.getZ(), GenericMath.ceil(maxZ) - boundingBox.getMax(Axis.Z)); + } + + if (Double.isNaN(correctedZ)) { + return movement; + } + + return Vector3d.from(correctedX, movement.getY(), correctedZ); + } + + private double limitMovement(double movement, double limit) { + if (limit < 0) { + // Return NaN to indicate outside of border + return Double.NaN; + } + + if (limit < COLLISION_TOLERANCE) { + return 0; + } + + return Math.min(movement, limit); + } + /** * Updates the world border's minimum and maximum properties */ 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 2481028a4..bfe3f4417 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 @@ -166,4 +166,22 @@ public class BlockCollision { } return offset; } + + /** + * Checks if this block collision is below the given bounding box. + * + * @param blockY the y position of the block in the world + * @param boundingBox the bounding box to compare + * @return true if this block collision is below the bounding box + */ + public boolean isBelow(int blockY, BoundingBox boundingBox) { + double minY = boundingBox.getMiddleY() - boundingBox.getSizeY() / 2; + for (BoundingBox b : boundingBoxes) { + double offset = blockY + b.getMiddleY() + b.getSizeY() / 2 - minY; + if (offset > CollisionManager.COLLISION_TOLERANCE) { + return false; + } + } + return true; + } } \ No newline at end of file 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 d1dd24855..b668a88cf 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 @@ -37,6 +37,7 @@ 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.vehicle.ClientVehicle; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.level.block.property.Properties; @@ -347,18 +348,31 @@ public class PistonBlockEntity { blockMovement = 1f - lastProgress; } - BoundingBox playerBoundingBox = session.getCollisionManager().getPlayerBoundingBox(); + boolean onGround; + BoundingBox playerBoundingBox; + if (session.getPlayerEntity().getVehicle() instanceof ClientVehicle clientVehicle && clientVehicle.isClientControlled()) { + onGround = session.getPlayerEntity().getVehicle().isOnGround(); + playerBoundingBox = clientVehicle.getVehicleComponent().getBoundingBox(); + } else { + onGround = session.getPlayerEntity().isOnGround(); + playerBoundingBox = session.getCollisionManager().getPlayerBoundingBox(); + } + // Shrink the collision in the other axes slightly, to avoid false positives when pressed up against the side of blocks Vector3d shrink = Vector3i.ONE.sub(direction.abs()).toDouble().mul(CollisionManager.COLLISION_TOLERANCE * 2); - playerBoundingBox.setSizeX(playerBoundingBox.getSizeX() - shrink.getX()); - playerBoundingBox.setSizeY(playerBoundingBox.getSizeY() - shrink.getY()); - playerBoundingBox.setSizeZ(playerBoundingBox.getSizeZ() - shrink.getZ()); + double sizeX = playerBoundingBox.getSizeX(); + double sizeY = playerBoundingBox.getSizeY(); + double sizeZ = playerBoundingBox.getSizeZ(); + + playerBoundingBox.setSizeX(sizeX - shrink.getX()); + playerBoundingBox.setSizeY(sizeY - shrink.getY()); + playerBoundingBox.setSizeZ(sizeZ - shrink.getZ()); // Resolve collision with the piston head BlockState pistonHeadId = Blocks.PISTON_HEAD.defaultBlockState() .withValue(Properties.SHORT, false) .withValue(Properties.FACING, orientation); - pushPlayerBlock(pistonHeadId, getPistonHeadPos().toDouble(), blockMovement, playerBoundingBox); + pushPlayerBlock(pistonHeadId, getPistonHeadPos().toDouble(), blockMovement, playerBoundingBox, onGround); // Resolve collision with any attached moving blocks, but skip slime blocks // This prevents players from being launched by slime blocks covered by other blocks @@ -366,7 +380,7 @@ public class PistonBlockEntity { BlockState state = entry.getValue(); if (!state.is(Blocks.SLIME_BLOCK)) { Vector3d blockPos = entry.getKey().toDouble(); - pushPlayerBlock(state, blockPos, blockMovement, playerBoundingBox); + pushPlayerBlock(state, blockPos, blockMovement, playerBoundingBox, onGround); } } // Resolve collision with slime blocks @@ -374,14 +388,14 @@ public class PistonBlockEntity { BlockState state = entry.getValue(); if (state.is(Blocks.SLIME_BLOCK)) { Vector3d blockPos = entry.getKey().toDouble(); - pushPlayerBlock(state, blockPos, blockMovement, playerBoundingBox); + pushPlayerBlock(state, blockPos, blockMovement, playerBoundingBox, onGround); } } // Undo shrink - playerBoundingBox.setSizeX(playerBoundingBox.getSizeX() + shrink.getX()); - playerBoundingBox.setSizeY(playerBoundingBox.getSizeY() + shrink.getY()); - playerBoundingBox.setSizeZ(playerBoundingBox.getSizeZ() + shrink.getZ()); + playerBoundingBox.setSizeX(sizeX); + playerBoundingBox.setSizeY(sizeY); + playerBoundingBox.setSizeZ(sizeZ); } /** @@ -391,20 +405,22 @@ public class PistonBlockEntity { * @param playerBoundingBox The player's bounding box * @return True if the player attached, otherwise false */ - private boolean isPlayerAttached(Vector3d blockPos, BoundingBox playerBoundingBox) { + private boolean isPlayerAttached(Vector3d blockPos, BoundingBox playerBoundingBox, boolean onGround) { if (orientation.isVertical()) { return false; } - return session.getPlayerEntity().isOnGround() && HONEY_BOUNDING_BOX.checkIntersection(blockPos, playerBoundingBox); + return onGround && HONEY_BOUNDING_BOX.checkIntersection(blockPos, playerBoundingBox); } /** * Launches a player if the player is on the pushing side of the slime block * * @param blockPos The position of the slime block - * @param playerPos The player's position + * @param playerBoundingBox The player's bounding box */ - private void applySlimeBlockMotion(Vector3d blockPos, Vector3d playerPos) { + private void applySlimeBlockMotion(Vector3d blockPos, BoundingBox playerBoundingBox) { + Vector3d playerPos = Vector3d.from(playerBoundingBox.getMiddleX(), playerBoundingBox.getMiddleY(), playerBoundingBox.getMiddleZ()); + Direction movementDirection = orientation; // Invert direction when pulling if (action == PistonValueType.PULLING) { @@ -470,7 +486,7 @@ public class PistonBlockEntity { return maxIntersection; } - private void pushPlayerBlock(BlockState state, Vector3d startingPos, double blockMovement, BoundingBox playerBoundingBox) { + private void pushPlayerBlock(BlockState state, Vector3d startingPos, double blockMovement, BoundingBox playerBoundingBox, boolean onGround) { PistonCache pistonCache = session.getPistonCache(); Vector3d movement = getMovement().toDouble(); // Check if the player collides with the movingBlock block entity @@ -480,12 +496,12 @@ public class PistonBlockEntity { if (state.is(Blocks.SLIME_BLOCK)) { pistonCache.setPlayerSlimeCollision(true); - applySlimeBlockMotion(finalBlockPos, Vector3d.from(playerBoundingBox.getMiddleX(), playerBoundingBox.getMiddleY(), playerBoundingBox.getMiddleZ())); + applySlimeBlockMotion(finalBlockPos, playerBoundingBox); } } Vector3d blockPos = startingPos.add(movement.mul(blockMovement)); - if (state.is(Blocks.HONEY_BLOCK) && isPlayerAttached(blockPos, playerBoundingBox)) { + if (state.is(Blocks.HONEY_BLOCK) && isPlayerAttached(blockPos, playerBoundingBox, onGround)) { pistonCache.setPlayerCollided(true); pistonCache.setPlayerAttachedToHoney(true); @@ -508,7 +524,7 @@ public class PistonBlockEntity { if (state.is(Blocks.SLIME_BLOCK)) { pistonCache.setPlayerSlimeCollision(true); - applySlimeBlockMotion(blockPos, Vector3d.from(playerBoundingBox.getMiddleX(), playerBoundingBox.getMiddleY(), playerBoundingBox.getMiddleZ())); + applySlimeBlockMotion(blockPos, playerBoundingBox); } } } @@ -584,7 +600,7 @@ public class PistonBlockEntity { movingBlockMap.put(getPistonHeadPos(), this); Vector3i movement = getMovement(); - BoundingBox playerBoundingBox = session.getCollisionManager().getPlayerBoundingBox().clone(); + BoundingBox playerBoundingBox = session.getCollisionManager().getActiveBoundingBox().clone(); if (orientation == Direction.UP) { // Extend the bounding box down, to catch collisions when the player is falling down playerBoundingBox.extend(0, -256, 0); @@ -628,17 +644,19 @@ public class PistonBlockEntity { return; } placedFinalBlocks = true; + Vector3i movement = getMovement(); + BoundingBox playerBoundingBox = session.getCollisionManager().getActiveBoundingBox().clone(); attachedBlocks.forEach((blockPos, state) -> { blockPos = blockPos.add(movement); // Don't place blocks that collide with the player - if (!SOLID_BOUNDING_BOX.checkIntersection(blockPos.toDouble(), session.getCollisionManager().getPlayerBoundingBox())) { + if (!SOLID_BOUNDING_BOX.checkIntersection(blockPos.toDouble(), playerBoundingBox)) { ChunkUtils.updateBlock(session, state, blockPos); } }); if (action == PistonValueType.PUSHING) { Vector3i pistonHeadPos = getPistonHeadPos().add(movement); - if (!SOLID_BOUNDING_BOX.checkIntersection(pistonHeadPos.toDouble(), session.getCollisionManager().getPlayerBoundingBox())) { + if (!SOLID_BOUNDING_BOX.checkIntersection(pistonHeadPos.toDouble(), playerBoundingBox)) { ChunkUtils.updateBlock(session, Blocks.PISTON_HEAD.defaultBlockState() .withValue(Properties.SHORT, false) .withValue(Properties.FACING, orientation), pistonHeadPos); 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 beb724ffb..1498c2184 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 @@ -52,6 +52,8 @@ public class BedrockPlayerInputTranslator extends PacketTranslator { @Override public void translate(GeyserSession session, RiderJumpPacket packet) { + session.getPlayerEntity().setVehicleJumpStrength(packet.getJumpStrength()); + Entity vehicle = session.getPlayerEntity().getVehicle(); if (vehicle instanceof AbstractHorseEntity) { ServerboundPlayerCommandPacket playerCommandPacket = new ServerboundPlayerCommandPacket(vehicle.getEntityId(), PlayerState.START_HORSE_JUMP, packet.getJumpStrength()); 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 601517523..ccd93ac97 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 @@ -101,6 +101,7 @@ public class JavaRespawnTranslator extends PacketTranslator Date: Fri, 16 Aug 2024 01:09:08 +0200 Subject: [PATCH 217/233] Fix: Invalid heads blocking inventory transactions (#4969) --- .../geyser/skin/FakeHeadProvider.java | 10 +++++-- .../translator/item/ItemTranslator.java | 28 ++++++++++++++----- 2 files changed, 29 insertions(+), 9 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 6f6bcb0ae..22786a4ee 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/FakeHeadProvider.java +++ b/core/src/main/java/org/geysermc/geyser/skin/FakeHeadProvider.java @@ -112,7 +112,13 @@ public class FakeHeadProvider { return; } - Map textures = profile.getTextures(false); + Map textures; + try { + textures = profile.getTextures(false); + } catch (IllegalStateException e) { + GeyserImpl.getInstance().getLogger().debug("Could not decode player head from profile %s, got: %s".formatted(profile, e.getMessage())); + textures = null; + } if (textures == null || textures.isEmpty()) { loadHead(session, entity, profile.getName()); @@ -214,4 +220,4 @@ public class FakeHeadProvider { } } -} \ No newline at end of file +} 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 aa0c3eb43..163eef20b 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,9 +25,6 @@ package org.geysermc.geyser.translator.item; -import org.geysermc.mcprotocollib.auth.GameProfile; -import org.geysermc.mcprotocollib.auth.GameProfile.Texture; -import org.geysermc.mcprotocollib.auth.GameProfile.TextureType; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.checkerframework.checker.nullness.qual.NonNull; @@ -43,8 +40,8 @@ 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.components.Rarity; -import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.item.type.BedrockRequiresTagItem; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; @@ -55,13 +52,24 @@ 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.auth.GameProfile; +import org.geysermc.mcprotocollib.auth.GameProfile.Texture; +import org.geysermc.mcprotocollib.auth.GameProfile.TextureType; import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.AttributeType; 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.*; +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.HolderSet; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemAttributeModifiers; import java.text.DecimalFormat; -import java.util.*; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public final class ItemTranslator { @@ -486,7 +494,13 @@ public final class ItemTranslator { GameProfile profile = components.get(DataComponentType.PROFILE); if (profile != null) { - Map textures = profile.getTextures(false); + Map textures; + try { + textures = profile.getTextures(false); + } catch (IllegalStateException e) { + GeyserImpl.getInstance().getLogger().debug("Could not decode player head from profile %s, got: %s".formatted(profile, e.getMessage())); + return null; + } if (textures == null || textures.isEmpty()) { return null; From bc7866541008f222554d93cde7ec45c344ed429d Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 21 Aug 2024 09:36:23 +0200 Subject: [PATCH 218/233] Indicate 1.21.21 support, update Bedrock protocol library dependencies (#4974) * Show 1.21.21 as being supported, bump Bedrock protocol library * Dont print debug --- README.md | 2 +- .../java/org/geysermc/geyser/network/GameProtocol.java | 2 +- gradle/libs.versions.toml | 10 ++++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 5e586463c..fb93a8808 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,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! ## Supported Versions -Geyser is currently supporting Minecraft Bedrock 1.20.80 - 1.21.20 and Minecraft Java Server 1.21/1.21.1. For more info please see [here](https://geysermc.org/wiki/geyser/supported-versions/). +Geyser is currently supporting Minecraft Bedrock 1.20.80 - 1.21.21 and Minecraft Java 1.21/1.21.1. For more information, please see [here](https://geysermc.org/wiki/geyser/supported-versions/). ## Setting Up Take a look [here](https://geysermc.org/wiki/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 422fa3d5a..baa1d24d0 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,7 @@ public final class GameProtocol { * release of the game that Geyser supports. */ public static final BedrockCodec DEFAULT_BEDROCK_CODEC = CodecProcessor.processCodec(Bedrock_v712.CODEC.toBuilder() - .minecraftVersion("1.21.20") + .minecraftVersion("1.21.20/1.21.21") .build()); /** diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 795d351ed..f49de8d20 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,9 @@ 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" -protocol = "3.0.0.Beta3-20240814.133201-7" +protocol-connection = "3.0.0.Beta3-20240819.124045-12" +protocol-common = "3.0.0.Beta3-20240819.124045-10" +protocol-codec = "3.0.0.Beta3-20240819.124045-13" raknet = "1.0.0.CR3-20240416.144209-1" minecraftauth = "4.1.1-20240806.235051-7" mcprotocollib = "1.21-20240725.013034-16" @@ -125,9 +127,9 @@ viaproxy = { group = "net.raphimc", name = "ViaProxy", version.ref = "viaproxy" viaversion = { group = "com.viaversion", name = "viaversion", version.ref = "viaversion" } websocket = { group = "org.java-websocket", name = "Java-WebSocket", version.ref = "websocket" } -protocol-common = { group = "org.cloudburstmc.protocol", name = "common", version.ref = "protocol" } -protocol-codec = { group = "org.cloudburstmc.protocol", name = "bedrock-codec", version.ref = "protocol" } -protocol-connection = { group = "org.cloudburstmc.protocol", name = "bedrock-connection", version.ref = "protocol" } +protocol-common = { group = "org.cloudburstmc.protocol", name = "common", version.ref = "protocol-common" } +protocol-codec = { group = "org.cloudburstmc.protocol", name = "bedrock-codec", version.ref = "protocol-codec" } +protocol-connection = { group = "org.cloudburstmc.protocol", name = "bedrock-connection", version.ref = "protocol-connection" } math = { group = "org.cloudburstmc.math", name = "immutable", version = "2.0" } From b792f72ec70706ce1158d3745fd164e73edf6ae3 Mon Sep 17 00:00:00 2001 From: Tim203 Date: Wed, 21 Aug 2024 13:46:10 +0200 Subject: [PATCH 219/233] Fix invalid ping version causing "Unable to connect to world" --- .../geyser/network/netty/GeyserServer.java | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 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 a67bd8a32..5166bde4d 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 @@ -84,10 +84,11 @@ public final class GeyserServer { /* The following constants are all used to ensure the ping does not reach a length where it is unparsable by the Bedrock client */ - private static final int MINECRAFT_VERSION_BYTES_LENGTH = GameProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion().getBytes(StandardCharsets.UTF_8).length; + private static final String PING_VERSION = pingVersion(); + private static final int PING_VERSION_BYTES_LENGTH = PING_VERSION.getBytes(StandardCharsets.UTF_8).length; private static final int BRAND_BYTES_LENGTH = GeyserImpl.NAME.getBytes(StandardCharsets.UTF_8).length; /** - * The MOTD, sub-MOTD and Minecraft version ({@link #MINECRAFT_VERSION_BYTES_LENGTH}) combined cannot reach this length. + * The MOTD, sub-MOTD and Minecraft version ({@link #PING_VERSION_BYTES_LENGTH}) combined cannot reach this length. */ private static final int MAGIC_RAKNET_LENGTH = 338; @@ -316,7 +317,7 @@ public final class GeyserServer { .gameType("Survival") // Can only be Survival or Creative as of 1.16.210.59 .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. + .version(PING_VERSION) .ipv4Port(this.broadcastPort) .ipv6Port(this.broadcastPort) .serverId(channel.config().getOption(RakChannelOption.RAK_GUID)); @@ -367,15 +368,15 @@ public final class GeyserServer { // We don't know why, though byte[] motdArray = pong.motd().getBytes(StandardCharsets.UTF_8); int subMotdLength = pong.subMotd().getBytes(StandardCharsets.UTF_8).length; - if (motdArray.length + subMotdLength > (MAGIC_RAKNET_LENGTH - MINECRAFT_VERSION_BYTES_LENGTH)) { + if (motdArray.length + subMotdLength > (MAGIC_RAKNET_LENGTH - PING_VERSION_BYTES_LENGTH)) { // Shorten the sub-MOTD first since that only appears locally if (subMotdLength > BRAND_BYTES_LENGTH) { pong.subMotd(GeyserImpl.NAME); subMotdLength = BRAND_BYTES_LENGTH; } - if (motdArray.length > (MAGIC_RAKNET_LENGTH - MINECRAFT_VERSION_BYTES_LENGTH - subMotdLength)) { + if (motdArray.length > (MAGIC_RAKNET_LENGTH - PING_VERSION_BYTES_LENGTH - subMotdLength)) { // If the top MOTD is still too long, we chop it down - byte[] newMotdArray = new byte[MAGIC_RAKNET_LENGTH - MINECRAFT_VERSION_BYTES_LENGTH - subMotdLength]; + byte[] newMotdArray = new byte[MAGIC_RAKNET_LENGTH - PING_VERSION_BYTES_LENGTH - subMotdLength]; System.arraycopy(motdArray, 0, newMotdArray, 0, newMotdArray.length); pong.motd(new String(newMotdArray, StandardCharsets.UTF_8)); } @@ -390,6 +391,17 @@ public final class GeyserServer { return pong; } + private static String pingVersion() { + // BedrockPong version is required to not be empty as of 1.16.210.59. + // Can only contain . and numbers, so use the latest version instead of sending all + var version = GameProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion(); + var versionSplit = version.split("/"); + if (versionSplit.length > 1) { + version = versionSplit[versionSplit.length - 1]; + } + return version; + } + /** * @return the throwable from the given supplier, or the throwable caught while calling the supplier. */ From 6801338ff991dcad75bac09ca4edf44547630a13 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Thu, 22 Aug 2024 00:50:16 -0400 Subject: [PATCH 220/233] Another route of ensuring /help goes through to Bedrock --- .../protocol/java/JavaCommandsTranslator.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) 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 01da23809..6bbf0eb33 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 @@ -88,6 +88,7 @@ public class JavaCommandsTranslator extends PacketTranslator flags = Set.of(CommandData.Flag.NOT_CHEAT); + boolean helpAdded = false; + // Loop through all the found commands for (Map.Entry> entry : commands.entrySet()) { String commandName = entry.getValue().iterator().next(); // We know this has a value @@ -198,6 +201,18 @@ public class JavaCommandsTranslator extends PacketTranslator Date: Thu, 22 Aug 2024 13:16:07 -0400 Subject: [PATCH 221/233] Show the help command even with command suggestions disabled --- .../protocol/java/JavaCommandsTranslator.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) 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 6bbf0eb33..f189658cd 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 @@ -125,8 +125,9 @@ public class JavaCommandsTranslator extends PacketTranslator Date: Sun, 25 Aug 2024 21:31:03 +0200 Subject: [PATCH 222/233] Feature: Modrinth version names (#4989) * Feature: Version names on modrinth published builds * Also change the fabric/neoforge jar file names --- build-logic/src/main/kotlin/extensions.kt | 9 +++++++++ .../src/main/kotlin/geyser.modded-conventions.gradle.kts | 2 +- .../geyser.modrinth-uploading-conventions.gradle.kts | 3 ++- core/build.gradle.kts | 5 +---- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/build-logic/src/main/kotlin/extensions.kt b/build-logic/src/main/kotlin/extensions.kt index 41e11344b..1b81f6601 100644 --- a/build-logic/src/main/kotlin/extensions.kt +++ b/build-logic/src/main/kotlin/extensions.kt @@ -118,3 +118,12 @@ open class DownloadFilesTask : DefaultTask() { private fun calcExclusion(section: String, bit: Int, excludedOn: Int): String = if (excludedOn and bit > 0) section else "" +fun projectVersion(project: Project): String = + project.version.toString().replace("SNAPSHOT", "b" + buildNumber()) + +fun versionName(project: Project): String = + "Geyser-" + project.name.replaceFirstChar { it.uppercase() } + "-" + projectVersion(project) + +fun buildNumber(): Int = + (System.getenv("BUILD_NUMBER"))?.let { Integer.parseInt(it) } ?: -1 + 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 8a6602778..8584c13d4 100644 --- a/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts @@ -87,7 +87,7 @@ tasks { register("remapModrinthJar", RemapJarTask::class) { dependsOn(shadowJar) inputFile.set(shadowJar.get().archiveFile) - archiveVersion.set(project.version.toString() + "+build." + System.getenv("BUILD_NUMBER")) + archiveVersion.set(versionName(project)) archiveClassifier.set("") } } diff --git a/build-logic/src/main/kotlin/geyser.modrinth-uploading-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.modrinth-uploading-conventions.gradle.kts index fe2284137..d2e207fa4 100644 --- a/build-logic/src/main/kotlin/geyser.modrinth-uploading-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.modrinth-uploading-conventions.gradle.kts @@ -8,7 +8,8 @@ tasks.modrinth.get().dependsOn(tasks.modrinthSyncBody) modrinth { token.set(System.getenv("MODRINTH_TOKEN") ?: "") // Even though this is the default value, apparently this prevents GitHub Actions caching the token? projectId.set("geyser") - versionNumber.set(project.version as String + "-" + System.getenv("BUILD_NUMBER")) + versionName.set(versionName(project)) + versionNumber.set(projectVersion(project)) versionType.set("beta") changelog.set(System.getenv("CHANGELOG") ?: "") gameVersions.addAll("1.21", libs.minecraft.get().version as String) diff --git a/core/build.gradle.kts b/core/build.gradle.kts index acd6c5147..8d022271b 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -103,9 +103,6 @@ sourceSets { } } -fun buildNumber(): Int = - (System.getenv("BUILD_NUMBER"))?.let { Integer.parseInt(it) } ?: -1 - fun isDevBuild(branch: String, repository: String): Boolean { return branch != "master" || repository.equals("https://github.com/GeyserMC/Geyser", ignoreCase = true).not() } @@ -139,7 +136,7 @@ inner class GitInfo { buildNumber = buildNumber() isDev = isDevBuild(branch, repository) - val projectVersion = if (isDev) project.version else project.version.toString().replace("SNAPSHOT", "b${buildNumber}") + val projectVersion = if (isDev) project.version else projectVersion(project) version = "$projectVersion ($gitVersion)" } } From 3be9b8a183aa2fe798b6b8d19e95eb74ba096f0a Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Mon, 26 Aug 2024 00:48:42 -0400 Subject: [PATCH 223/233] Fix moving items from output slot over multiple actions (#4993) * Fix moving items from output slot over multiple actions * Refactor and use temp slot * Ensure source slot is not cursor --- .../geyser/inventory/click/ClickPlan.java | 21 +++ .../inventory/InventoryTranslator.java | 146 ++++++++++++++---- 2 files changed, 137 insertions(+), 30 deletions(-) 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 53b02ef88..9d6f4d3e3 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 @@ -162,6 +162,27 @@ public final class ClickPlan { finished = true; } + public Inventory getInventory() { + return inventory; + } + + /** + * Test if the item stacks with another item in the specified slot. + * This will check the simulated inventory without copying. + */ + public boolean canStack(int slot, GeyserItemStack item) { + GeyserItemStack slotItem = simulatedItems.getOrDefault(slot, inventory.getItem(slot)); + return InventoryUtils.canStack(slotItem, item); + } + + /** + * Test if the specified slot is empty. + * This will check the simulated inventory without copying. + */ + public boolean isEmpty(int slot) { + return simulatedItems.getOrDefault(slot, inventory.getItem(slot)).isEmpty(); + } + public GeyserItemStack getItem(int slot) { return simulatedItems.computeIfAbsent(slot, k -> inventory.getItem(slot).copy()); } 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 546ebda19..afa11c982 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 @@ -201,6 +201,9 @@ public abstract class InventoryTranslator { public ItemStackResponse translateRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) { ClickPlan plan = new ClickPlan(session, this, inventory); IntSet affectedSlots = new IntOpenHashSet(); + int pendingOutput = 0; + int savedTempSlot = -1; + for (ItemStackRequestAction action : request.getActions()) { GeyserItemStack cursor = session.getPlayerInventory().getCursor(); switch (action.getType()) { @@ -241,6 +244,65 @@ public abstract class InventoryTranslator { return rejectRequest(request, false); } + // Handle partial transfer of output slot + if (pendingOutput == 0 && !isSourceCursor && getSlotType(sourceSlot) == SlotType.OUTPUT + && transferAction.getCount() < plan.getItem(sourceSlot).getAmount()) { + // Cursor as dest should always be full transfer. + if (isDestCursor) { + return rejectRequest(request); + } + + if (!plan.getCursor().isEmpty()) { + savedTempSlot = findTempSlot(plan, plan.getCursor(), true); + if (savedTempSlot == -1) { + return rejectRequest(request); + } + plan.add(Click.LEFT, savedTempSlot); + } + + // Pickup entire stack from output + pendingOutput = plan.getItem(sourceSlot).getAmount(); + plan.add(Click.LEFT, sourceSlot); + } + + // Continue transferring items from output that is currently stored in the cursor + if (pendingOutput > 0) { + if (isSourceCursor || getSlotType(sourceSlot) != SlotType.OUTPUT + || transferAction.getCount() > pendingOutput + || destSlot == savedTempSlot + || isDestCursor) { + return rejectRequest(request); + } + + // Make sure item can be placed here + GeyserItemStack destItem = plan.getItem(destSlot); + if (!destItem.isEmpty() && !InventoryUtils.canStack(destItem, plan.getCursor())) { + return rejectRequest(request); + } + + // TODO: Optimize using max stack size + if (pendingOutput == transferAction.getCount()) { + plan.add(Click.LEFT, destSlot); + } else { + for (int i = 0; i < transferAction.getCount(); i++) { + plan.add(Click.RIGHT, destSlot); + } + } + + pendingOutput -= transferAction.getCount(); + if (pendingOutput != plan.getCursor().getAmount()) { + return rejectRequest(request); + } + + if (pendingOutput == 0 && savedTempSlot != -1) { + plan.add(Click.LEFT, savedTempSlot); + savedTempSlot = -1; + } + + // Skip to next action + continue; + } + if (isSourceCursor && isDestCursor) { //??? return rejectRequest(request); } else if (isSourceCursor) { //releasing cursor @@ -271,7 +333,7 @@ public abstract class InventoryTranslator { return rejectRequest(request); } if (transferAction.getCount() != sourceAmount) { - int tempSlot = findTempSlot(inventory, cursor, false, sourceSlot); + int tempSlot = findTempSlot(plan, cursor, false, sourceSlot); if (tempSlot == -1) { return rejectRequest(request); } @@ -292,7 +354,7 @@ public abstract class InventoryTranslator { } else { //transfer from one slot to another int tempSlot = -1; if (!plan.getCursor().isEmpty()) { - tempSlot = findTempSlot(inventory, cursor, false, sourceSlot, destSlot); + tempSlot = findTempSlot(plan, cursor, getSlotType(sourceSlot) != SlotType.NORMAL, sourceSlot, destSlot); if (tempSlot == -1) { return rejectRequest(request); } @@ -440,6 +502,11 @@ public abstract class InventoryTranslator { return rejectRequest(request); } } + + if (pendingOutput != 0) { + return rejectRequest(request); + } + plan.execute(false); affectedSlots.addAll(plan.getAffectedSlots()); return acceptRequest(request, makeContainerEntries(session, inventory, affectedSlots)); @@ -536,7 +603,7 @@ public abstract class InventoryTranslator { } } else { GeyserItemStack cursor = session.getPlayerInventory().getCursor(); - int tempSlot = findTempSlot(inventory, cursor, true, sourceSlot, destSlot); + int tempSlot = findTempSlot(plan, cursor, true, sourceSlot, destSlot); if (tempSlot == -1) { return rejectRequest(request); } @@ -699,7 +766,7 @@ public abstract class InventoryTranslator { int javaSlot = bedrockSlotToJava(transferAction.getDestination()); if (isCursor(transferAction.getDestination())) { //TODO if (timesCrafted > 1) { - tempSlot = findTempSlot(inventory, GeyserItemStack.from(output), true); + tempSlot = findTempSlot(plan, GeyserItemStack.from(output), true); if (tempSlot == -1) { return rejectRequest(request); } @@ -836,49 +903,68 @@ public abstract class InventoryTranslator { } /** - * Try to find a slot that can temporarily store the given item. + * Try to find a slot that is preferably empty, or does not stack with a given item. * Only looks in the main inventory and hotbar (excluding offhand). - * Only slots that are empty or contain a different type of item are valid. + *

    + * Slots are searched in the reverse order that the bedrock client uses for quick moving. * - * @return java id for the temporary slot, or -1 if no viable slot was found + * @param plan used to check the simulated inventory + * @param item the item to temporarily store + * @param emptyOnly if only empty slots should be considered + * @param slotBlacklist list of slots to exclude; the items contained in these slots will also be checked for stacking + * @return the temp slot, or -1 if no suitable slot was found */ - //TODO: compatibility for simulated inventory (ClickPlan) - private static int findTempSlot(Inventory inventory, GeyserItemStack item, boolean emptyOnly, int... slotBlacklist) { - int offset = inventory.getJavaId() == 0 ? 1 : 0; //offhand is not a viable temp slot - HashSet itemBlacklist = new HashSet<>(slotBlacklist.length + 1); - itemBlacklist.add(item); + private static int findTempSlot(ClickPlan plan, GeyserItemStack item, boolean emptyOnly, int... slotBlacklist) { + IntSortedSet potentialSlots = new IntLinkedOpenHashSet(PLAYER_INVENTORY_SIZE); + int hotbarOffset = plan.getInventory().getOffsetForHotbar(0); - IntSet potentialSlots = new IntOpenHashSet(36); - for (int i = inventory.getSize() - (36 + offset); i < inventory.getSize() - offset; i++) { + // Add main inventory slots in reverse + for (int i = hotbarOffset - 1; i >= hotbarOffset - 27; i--) { potentialSlots.add(i); } + + // Add hotbar slots in reverse + for (int i = hotbarOffset + 8; i >= hotbarOffset; i--) { + potentialSlots.add(i); + } + for (int i : slotBlacklist) { potentialSlots.remove(i); - GeyserItemStack blacklistedItem = inventory.getItem(i); - if (!blacklistedItem.isEmpty()) { - itemBlacklist.add(blacklistedItem); + } + + // Prefer empty slots + IntIterator it = potentialSlots.iterator(); + while (it.hasNext()) { + int slot = it.nextInt(); + if (plan.isEmpty(slot)) { + return slot; } } - for (int i : potentialSlots) { - GeyserItemStack testItem = inventory.getItem(i); - if ((emptyOnly && !testItem.isEmpty())) { + if (emptyOnly) { + return -1; + } + + // No empty slots. Look for a slot that does not stack + it = potentialSlots.iterator(); + + outer: + while (it.hasNext()) { + int slot = it.nextInt(); + if (plan.canStack(slot, item)) { continue; } - boolean viable = true; - for (GeyserItemStack blacklistedItem : itemBlacklist) { - if (InventoryUtils.canStack(testItem, blacklistedItem)) { - viable = false; - break; + for (int blacklistedSlot : slotBlacklist) { + GeyserItemStack blacklistedItem = plan.getItem(blacklistedSlot); + if (plan.canStack(slot, blacklistedItem)) { + continue outer; } } - if (!viable) { - continue; - } - return i; + + return slot; } - //could not find a viable temp slot + return -1; } From 46b2c032154502378c2dcd20054703cc69deeae2 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Tue, 27 Aug 2024 05:37:01 -0400 Subject: [PATCH 224/233] Fix rare netid desync when crafting (#4997) --- .../geyser/translator/inventory/PlayerInventoryTranslator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 bc6ff2adf..21f45a5ca 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 @@ -123,7 +123,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { if (session.getGameMode() == GameMode.CREATIVE) { slotPacket.setItem(UNUSUABLE_CRAFTING_SPACE_BLOCK.apply(session.getUpstream().getProtocolVersion())); } else { - slotPacket.setItem(ItemTranslator.translateToBedrock(session, inventory.getItem(i).getItemStack())); + slotPacket.setItem(inventory.getItem(i).getItemData(session)); } session.sendUpstreamPacket(slotPacket); From 8356b63f5d52e8f8e61a7d0af71c924843503083 Mon Sep 17 00:00:00 2001 From: chris Date: Tue, 27 Aug 2024 18:40:22 +0200 Subject: [PATCH 225/233] Fix: Structure blocks/voids in recipes (#4999) * Fix: Structure blocks/voids in recipes * add gh issue link --- .../geyser/registry/populator/ItemRegistryPopulator.java | 5 +++++ 1 file changed, 5 insertions(+) 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 f11b58bfe..55d44c3d9 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 @@ -171,6 +171,11 @@ public class ItemRegistryPopulator { List creativeItems = new ArrayList<>(); Set noBlockDefinitions = new ObjectOpenHashSet<>(); + // Fix: Usage of structure blocks/voids in recipes + // https://github.com/GeyserMC/Geyser/issues/2890 + noBlockDefinitions.add("minecraft:structure_block"); + noBlockDefinitions.add("minecraft:structure_void"); + AtomicInteger creativeNetId = new AtomicInteger(); CreativeItemRegistryPopulator.populate(palette, definitions, itemBuilder -> { ItemData item = itemBuilder.netId(creativeNetId.incrementAndGet()).build(); From 1b17c6bd8e03c8ebc9c8949b6ea7a5888e6dea43 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Thu, 29 Aug 2024 14:50:26 -0400 Subject: [PATCH 226/233] Fix loom usage, and disconnect messages for all outdated clients (#5006) --- .../geysermc/geyser/network/UpstreamPacketHandler.java | 9 +++++---- gradle/libs.versions.toml | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) 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 e9c979b0c..adcaa2505 100644 --- a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java @@ -120,10 +120,11 @@ 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); - } + // A note on the following line: various older client versions have different forms of DisconnectPacket. + // Using only the latest BedrockCompat for such clients leads to inaccurate disconnect messages: https://github.com/GeyserMC/Geyser/issues/4378 + // This updates the BedrockCompat protocol if necessary: + session.getUpstream().getSession().setCodec(BedrockCompat.disconnectCompat(protocolVersion)); + session.disconnect(GeyserLocale.getLocaleStringLog("geyser.network.outdated.client", supportedVersions)); return false; } else { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f49de8d20..c564720a3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,9 +10,9 @@ 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" -protocol-connection = "3.0.0.Beta3-20240819.124045-12" -protocol-common = "3.0.0.Beta3-20240819.124045-10" -protocol-codec = "3.0.0.Beta3-20240819.124045-13" +protocol-connection = "3.0.0.Beta4-20240828.162251-1" +protocol-common = "3.0.0.Beta4-20240828.162251-1" +protocol-codec = "3.0.0.Beta4-20240828.162251-1" raknet = "1.0.0.CR3-20240416.144209-1" minecraftauth = "4.1.1-20240806.235051-7" mcprotocollib = "1.21-20240725.013034-16" From 63e60bc93cfc50bdaafafde6f39f6ebbe3f3d93c Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Thu, 29 Aug 2024 21:09:36 -0400 Subject: [PATCH 227/233] Allow Bedrock players to sleep on Fabric Fixes #5001 --- .../entity/player/BedrockMovePlayerTranslator.java | 8 ++++++++ 1 file changed, 8 insertions(+) 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 3faa3242b..6b403a99b 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 @@ -58,6 +58,14 @@ public class BedrockMovePlayerTranslator extends PacketTranslator Date: Fri, 30 Aug 2024 22:16:45 -0400 Subject: [PATCH 228/233] Ensure players aren't floating in their beds; improve Bedrock sleeping notifications --- .../entity/type/player/PlayerEntity.java | 14 +++++- .../type/player/SessionPlayerEntity.java | 2 +- .../geyser/network/UpstreamPacketHandler.java | 1 - .../player/BedrockMovePlayerTranslator.java | 2 +- .../java/JavaSystemChatTranslator.java | 43 ++++++++++++++++--- 5 files changed, 50 insertions(+), 12 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 4c67b882f..b326f2e04 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 @@ -42,7 +42,11 @@ 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.data.inventory.ItemData; -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.attribute.GeyserAttributeType; @@ -278,7 +282,13 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity { @Override public void setPosition(Vector3f position) { - super.setPosition(position.add(0, definition.offset(), 0)); + if (this.bedPosition != null) { + // As of Bedrock 1.21.22 and Fabric 1.21.1 + // Messes with Bedrock if we send this to the client itself, though. + super.setPosition(position.up(0.2f)); + } else { + super.setPosition(position.add(0, definition.offset(), 0)); + } } @Override 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 ccf2d25e6..f427b001a 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 @@ -140,7 +140,7 @@ public class SessionPlayerEntity extends PlayerEntity { if (valid) { // Don't update during session init session.getCollisionManager().updatePlayerBoundingBox(position); } - super.setPosition(position); + this.position = position.add(0, definition.offset(), 0); } /** 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 adcaa2505..5c48df1f9 100644 --- a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java @@ -29,7 +29,6 @@ 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; 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 6b403a99b..ee80cac16 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 @@ -61,7 +61,7 @@ public class BedrockMovePlayerTranslator extends PacketTranslator { @Override public void translate(GeyserSession session, ClientboundSystemChatPacket packet) { - if (packet.getContent() instanceof TranslatableComponent component && component.key().equals("chat.disabled.missingProfileKey")) { - // We likely got this message as a response to a player trying to chat - // As there SHOULD be no false flags for this, print every time it shows up in chat. - if (Boolean.parseBoolean(System.getProperty("Geyser.PrintSecureChatInformation", "true"))) { - session.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.chat.secure_info_1", session.locale())); - session.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.chat.secure_info_2", session.locale(), "https://geysermc.link/secure-chat")); + if (packet.getContent() instanceof TranslatableComponent component) { + if (component.key().equals("chat.disabled.missingProfileKey")) { + // We likely got this message as a response to a player trying to chat + // As there SHOULD be no false flags for this, print every time it shows up in chat. + if (Boolean.parseBoolean(System.getProperty("Geyser.PrintSecureChatInformation", "true"))) { + session.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.chat.secure_info_1", session.locale())); + session.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.chat.secure_info_2", session.locale(), "https://geysermc.link/secure-chat")); + } + } else if (component.key().equals("sleep.players_sleeping")) { + if (component.arguments().size() == 2) { + // Hack FYI, but it allows Bedrock players to easily understand this information + // without it being covered up or saying the night is being slept through. + int numPlayersSleeping = ((Number) component.arguments().get(0).value()).intValue(); + int totalPlayersNeeded = ((Number) component.arguments().get(1).value()).intValue(); + LevelEventGenericPacket sleepInfoPacket = new LevelEventGenericPacket(); + sleepInfoPacket.setType(LevelEvent.SLEEPING_PLAYERS); + sleepInfoPacket.setTag(NbtMap.builder() + .putInt("ableToSleep", totalPlayersNeeded) + .putInt("overworldPlayerCount", totalPlayersNeeded) + .putInt("sleepingPlayerCount", numPlayersSleeping) + .build()); + session.sendUpstreamPacket(sleepInfoPacket); + } + } else if (component.key().equals("sleep.skipping_night")) { + LevelEventGenericPacket sleepInfoPacket = new LevelEventGenericPacket(); + sleepInfoPacket.setType(LevelEvent.SLEEPING_PLAYERS); + sleepInfoPacket.setTag(NbtMap.builder() + .putInt("ableToSleep", 1) + .putInt("overworldPlayerCount", 1) + .putInt("sleepingPlayerCount", 1) + .build()); + session.sendUpstreamPacket(sleepInfoPacket); } } From 1ab3f1f2e06de06720154f205a2f5bcf8402bf31 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Sun, 1 Sep 2024 15:34:53 -0400 Subject: [PATCH 229/233] Improve command registration timing on Velocity/BungeeCord (#5013) --- .../bungeecord/GeyserBungeePlugin.java | 28 +++++++++-------- .../neoforge/GeyserNeoForgeBootstrap.java | 1 + .../platform/spigot/GeyserSpigotPlugin.java | 2 +- .../velocity/GeyserVelocityPlugin.java | 30 ++++++++++--------- 4 files changed, 33 insertions(+), 28 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 e2735c80e..7adfd488f 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 @@ -111,6 +111,21 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { if (geyser == null) { return; // Config did not load properly! } + + // After Geyser initialize for parity with other platforms. + var sourceConverter = new CommandSourceConverter<>( + CommandSender.class, + id -> getProxy().getPlayer(id), + () -> getProxy().getConsole(), + BungeeCommandSource::new + ); + CommandManager cloud = new BungeeCommandManager<>( + this, + ExecutionCoordinator.simpleCoordinator(), + sourceConverter + ); + this.commandRegistry = new CommandRegistry(geyser, cloud, false); // applying root permission would be a breaking change because we can't register permission defaults + // 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 @@ -150,19 +165,6 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { } this.geyserLogger.setDebug(geyserConfig.isDebugMode()); GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); - } else { - var sourceConverter = new CommandSourceConverter<>( - CommandSender.class, - id -> getProxy().getPlayer(id), - () -> getProxy().getConsole(), - BungeeCommandSource::new - ); - CommandManager cloud = new BungeeCommandManager<>( - this, - ExecutionCoordinator.simpleCoordinator(), - sourceConverter - ); - this.commandRegistry = new CommandRegistry(geyser, cloud, false); // applying root permission would be a breaking change because we can't register permission defaults } // Force-disable query if enabled, or else Geyser won't enable 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 7d3b9dc5f..ad56eda39 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 @@ -82,6 +82,7 @@ public class GeyserNeoForgeBootstrap extends GeyserModBootstrap { ); GeyserNeoForgeCommandRegistry registry = new GeyserNeoForgeCommandRegistry(getGeyser(), cloud); this.setCommandRegistry(registry); + // An auxiliary listener for registering undefined permissions belonging to commands. See javadocs for more info. NeoForge.EVENT_BUS.addListener(EventPriority.LOWEST, registry::onPermissionGatherForUndefined); } 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 c52927a83..a2d5c992b 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 @@ -181,7 +181,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { return; } - // Create command manager early so we can add Geyser extension commands + // Register commands after Geyser initialization, but before the server starts. var sourceConverter = new CommandSourceConverter<>( CommandSender.class, Bukkit::getPlayer, 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 413355813..8fa47f569 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 @@ -109,6 +109,22 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { this.geyser = GeyserImpl.load(PlatformType.VELOCITY, this); this.geyserInjector = new GeyserVelocityInjector(proxyServer); + + // We need to register commands here, rather than in onGeyserEnable which is invoked during the appropriate ListenerBoundEvent. + // Reason: players can connect after a listener is bound, and a player join locks registration to the cloud CommandManager. + var sourceConverter = new CommandSourceConverter<>( + CommandSource.class, + id -> proxyServer.getPlayer(id).orElse(null), + proxyServer::getConsoleCommandSource, + VelocityCommandSource::new + ); + CommandManager cloud = new VelocityCommandManager<>( + container, + proxyServer, + ExecutionCoordinator.simpleCoordinator(), + sourceConverter + ); + this.commandRegistry = new CommandRegistry(geyser, cloud, false); // applying root permission would be a breaking change because we can't register permission defaults } @Override @@ -123,20 +139,6 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { } this.geyserLogger.setDebug(geyserConfig.isDebugMode()); GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); - } else { - var sourceConverter = new CommandSourceConverter<>( - CommandSource.class, - id -> proxyServer.getPlayer(id).orElse(null), - proxyServer::getConsoleCommandSource, - VelocityCommandSource::new - ); - CommandManager cloud = new VelocityCommandManager<>( - container, - proxyServer, - ExecutionCoordinator.simpleCoordinator(), - sourceConverter - ); - this.commandRegistry = new CommandRegistry(geyser, cloud, false); // applying root permission would be a breaking change because we can't register permission defaults } GeyserImpl.start(); From 74034f078338e3bb27092b72e9067e6f5dd3968a Mon Sep 17 00:00:00 2001 From: RK_01 <50594595+RaphiMC@users.noreply.github.com> Date: Mon, 2 Sep 2024 22:08:43 +0200 Subject: [PATCH 230/233] Fix PARTICLES_DRAGON_BLOCK_BREAK translation (#5015) --- .../protocol/java/level/JavaLevelEventTranslator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 c10cfa018..f54de1b68 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 @@ -293,7 +293,7 @@ public class JavaLevelEventTranslator extends PacketTranslator { effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_GENERIC_SPAWN); - effectPacket.setData(61); + effectPacket.setData(65); } case PARTICLES_WATER_EVAPORATING -> { effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_EVAPORATE_WATER); From 65cb15400a4ac28d9a622004713b7ac59969e90e Mon Sep 17 00:00:00 2001 From: chris Date: Tue, 3 Sep 2024 01:04:44 +0200 Subject: [PATCH 231/233] Fix: Broadcast port system property not being read on Geyser-Standalone (#4942) * this is supposed to work on standalone aswell * Update core/src/main/java/org/geysermc/geyser/GeyserImpl.java Co-authored-by: Konicai <71294714+Konicai@users.noreply.github.com> * Update core/src/main/java/org/geysermc/geyser/GeyserImpl.java Co-authored-by: Konicai <71294714+Konicai@users.noreply.github.com> * address review --------- Co-authored-by: Konicai <71294714+Konicai@users.noreply.github.com> --- .../java/org/geysermc/geyser/GeyserImpl.java | 36 ++++++++++--------- .../geyser/network/netty/GeyserServer.java | 5 --- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 8febf4d21..bc6108abf 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -363,22 +363,6 @@ public class GeyserImpl implements GeyserApi, EventRegistrar { } } - 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); - } - if (platformType != PlatformType.VIAPROXY) { boolean floodgatePresent = bootstrap.testFloodgatePluginPresent(); if (config.getRemote().authType() == AuthType.FLOODGATE && !floodgatePresent) { @@ -393,6 +377,26 @@ public class GeyserImpl implements GeyserApi, EventRegistrar { } } + // Now that the Bedrock port may have been changed, also check the broadcast port (configurable on all platforms) + String broadcastPort = System.getProperty("geyserBroadcastPort", ""); + if (!broadcastPort.isEmpty()) { + try { + int parsedPort = Integer.parseInt(broadcastPort); + if (parsedPort < 1 || parsedPort > 65535) { + throw new NumberFormatException("The broadcast port must be between 1 and 65535 inclusive!"); + } + config.getBedrock().setBroadcastPort(parsedPort); + logger.info("Broadcast port set from system property: " + parsedPort); + } catch (NumberFormatException e) { + logger.error(String.format("Invalid broadcast port from system property: %s! Defaulting to configured port.", broadcastPort + " (" + e.getMessage() + ")")); + } + } + + // It's set to 0 only if no system property or manual config value was set + if (config.getBedrock().broadcastPort() == 0) { + config.getBedrock().setBroadcastPort(config.getBedrock().port()); + } + String remoteAddress = config.getRemote().address(); // Filters whether it is not an IP address or localhost, because otherwise it is not possible to find out an SRV entry. if (!remoteAddress.matches(IP_REGEX) && !remoteAddress.equalsIgnoreCase("localhost")) { 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 5166bde4d..efbd8bdff 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 @@ -144,11 +144,6 @@ public final class GeyserServer { 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(); } From f8884568ee717cda9314fb40ae0c7913bd601596 Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Tue, 3 Sep 2024 00:54:50 -0400 Subject: [PATCH 232/233] Gradle: avoid cross-configuration and enable configuration-on-demand (#5012) --- ap/build.gradle.kts | 3 + bootstrap/bungeecord/build.gradle.kts | 5 ++ bootstrap/mod/build.gradle.kts | 4 ++ bootstrap/mod/fabric/build.gradle.kts | 5 ++ bootstrap/mod/neoforge/build.gradle.kts | 13 ++-- bootstrap/spigot/build.gradle.kts | 5 ++ bootstrap/standalone/build.gradle.kts | 1 + bootstrap/velocity/build.gradle.kts | 5 ++ bootstrap/viaproxy/build.gradle.kts | 4 ++ build-logic/build.gradle.kts | 5 ++ build-logic/settings.gradle.kts | 2 +- .../kotlin/geyser.base-conventions.gradle.kts | 69 ++++++++++++++----- .../main/kotlin/geyser.build-logic.gradle.kts | 45 ------------ .../geyser.modded-conventions.gradle.kts | 4 +- .../geyser.platform-conventions.gradle.kts | 19 ++++- build.gradle.kts | 52 +------------- common/build.gradle.kts | 1 + core/build.gradle.kts | 1 + gradle.properties | 1 + gradle/libs.versions.toml | 2 +- 20 files changed, 123 insertions(+), 123 deletions(-) delete mode 100644 build-logic/src/main/kotlin/geyser.build-logic.gradle.kts diff --git a/ap/build.gradle.kts b/ap/build.gradle.kts index e69de29bb..6c456c21b 100644 --- a/ap/build.gradle.kts +++ b/ap/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("geyser.base-conventions") +} diff --git a/bootstrap/bungeecord/build.gradle.kts b/bootstrap/bungeecord/build.gradle.kts index 5fe7ea3d1..1564b7f75 100644 --- a/bootstrap/bungeecord/build.gradle.kts +++ b/bootstrap/bungeecord/build.gradle.kts @@ -1,3 +1,8 @@ +plugins { + id("geyser.platform-conventions") + id("geyser.modrinth-uploading-conventions") +} + dependencies { api(projects.core) diff --git a/bootstrap/mod/build.gradle.kts b/bootstrap/mod/build.gradle.kts index 57f11b2c7..c43f123ec 100644 --- a/bootstrap/mod/build.gradle.kts +++ b/bootstrap/mod/build.gradle.kts @@ -1,3 +1,7 @@ +plugins { + id("geyser.modded-conventions") +} + architectury { common("neoforge", "fabric") } diff --git a/bootstrap/mod/fabric/build.gradle.kts b/bootstrap/mod/fabric/build.gradle.kts index fd9d7e99d..56bec322e 100644 --- a/bootstrap/mod/fabric/build.gradle.kts +++ b/bootstrap/mod/fabric/build.gradle.kts @@ -1,3 +1,8 @@ +plugins { + id("geyser.modded-conventions") + id("geyser.modrinth-uploading-conventions") +} + architectury { platformSetupLoomIde() fabric() diff --git a/bootstrap/mod/neoforge/build.gradle.kts b/bootstrap/mod/neoforge/build.gradle.kts index 81a35a58b..4ab005b4f 100644 --- a/bootstrap/mod/neoforge/build.gradle.kts +++ b/bootstrap/mod/neoforge/build.gradle.kts @@ -1,13 +1,18 @@ -// This is provided by "org.cloudburstmc.math.mutable" too, so yeet. -// NeoForge's class loader is *really* annoying. -provided("org.cloudburstmc.math", "api") -provided("com.google.errorprone", "error_prone_annotations") +plugins { + id("geyser.modded-conventions") + id("geyser.modrinth-uploading-conventions") +} architectury { platformSetupLoomIde() neoForge() } +// This is provided by "org.cloudburstmc.math.mutable" too, so yeet. +// NeoForge's class loader is *really* annoying. +provided("org.cloudburstmc.math", "api") +provided("com.google.errorprone", "error_prone_annotations") + val includeTransitive: Configuration = configurations.getByName("includeTransitive") dependencies { diff --git a/bootstrap/spigot/build.gradle.kts b/bootstrap/spigot/build.gradle.kts index f680b1949..feabfdd7a 100644 --- a/bootstrap/spigot/build.gradle.kts +++ b/bootstrap/spigot/build.gradle.kts @@ -1,3 +1,8 @@ +plugins { + id("geyser.platform-conventions") + id("geyser.modrinth-uploading-conventions") +} + dependencies { api(projects.core) api(libs.erosion.bukkit.common) { diff --git a/bootstrap/standalone/build.gradle.kts b/bootstrap/standalone/build.gradle.kts index fd81dad63..b210693c1 100644 --- a/bootstrap/standalone/build.gradle.kts +++ b/bootstrap/standalone/build.gradle.kts @@ -2,6 +2,7 @@ import com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCach plugins { application + id("geyser.platform-conventions") } val terminalConsoleVersion = "1.2.0" diff --git a/bootstrap/velocity/build.gradle.kts b/bootstrap/velocity/build.gradle.kts index 93e0c9c93..05035e271 100644 --- a/bootstrap/velocity/build.gradle.kts +++ b/bootstrap/velocity/build.gradle.kts @@ -1,3 +1,8 @@ +plugins { + id("geyser.platform-conventions") + id("geyser.modrinth-uploading-conventions") +} + dependencies { annotationProcessor(libs.velocity.api) api(projects.core) diff --git a/bootstrap/viaproxy/build.gradle.kts b/bootstrap/viaproxy/build.gradle.kts index 254787743..c13862a27 100644 --- a/bootstrap/viaproxy/build.gradle.kts +++ b/bootstrap/viaproxy/build.gradle.kts @@ -1,3 +1,7 @@ +plugins { + id("geyser.platform-conventions") +} + dependencies { api(projects.core) diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts index 190386667..b87490880 100644 --- a/build-logic/build.gradle.kts +++ b/build-logic/build.gradle.kts @@ -12,9 +12,14 @@ repositories { } dependencies { + // This is for the LibsAccessor.kt hack // this is OK as long as the same version catalog is used in the main build and build-logic // see https://github.com/gradle/gradle/issues/15383#issuecomment-779893192 implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location)) + + // This is for applying plugins, and using the version from the libs.versions.toml + // Unfortunately they still need to be applied by their string name in the convention scripts. + implementation(libs.lombok) implementation(libs.indra) implementation(libs.shadow) implementation(libs.architectury.plugin) diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts index 63bde189b..bd4560d11 100644 --- a/build-logic/settings.gradle.kts +++ b/build-logic/settings.gradle.kts @@ -8,4 +8,4 @@ dependencyResolutionManagement { } } -rootProject.name = "build-logic" \ No newline at end of file +rootProject.name = "build-logic" 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 950c0184b..093f0a8c0 100644 --- a/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.base-conventions.gradle.kts @@ -3,9 +3,10 @@ plugins { id("net.kyori.indra") } -dependencies { - compileOnly("org.checkerframework", "checker-qual", "3.19.0") -} +val rootProperties: Map = project.rootProject.properties +group = rootProperties["group"] as String + "." + rootProperties["id"] as String +version = rootProperties["version"] as String +description = rootProperties["description"] as String indra { github("GeyserMC", "Geyser") { @@ -20,18 +21,52 @@ 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/neoforge.mods.toml")) { - expand( - "id" to "geyser", - "name" to "Geyser", - "version" to project.version, - "description" to project.description, - "url" to "https://geysermc.org", - "author" to "GeyserMC" - ) - } +dependencies { + compileOnly("org.checkerframework", "checker-qual", libs.checker.qual.get().version) +} + +repositories { + // mavenLocal() + + mavenCentral() + + // Floodgate, Cumulus etc. + maven("https://repo.opencollab.dev/main") + + // Paper, Velocity + maven("https://repo.papermc.io/repository/maven-public") + + // Spigot + maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots") { + mavenContent { snapshotsOnly() } } -} \ No newline at end of file + + // BungeeCord + maven("https://oss.sonatype.org/content/repositories/snapshots") { + mavenContent { snapshotsOnly() } + } + + // NeoForge + maven("https://maven.neoforged.net/releases") { + mavenContent { releasesOnly() } + } + + // Minecraft + maven("https://libraries.minecraft.net") { + name = "minecraft" + mavenContent { releasesOnly() } + } + + // ViaVersion + maven("https://repo.viaversion.com") { + name = "viaversion" + } + + // Jitpack for e.g. MCPL + maven("https://jitpack.io") { + content { includeGroupByRegex("com\\.github\\..*") } + } + + // For Adventure snapshots + maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") +} diff --git a/build-logic/src/main/kotlin/geyser.build-logic.gradle.kts b/build-logic/src/main/kotlin/geyser.build-logic.gradle.kts deleted file mode 100644 index b6168507e..000000000 --- a/build-logic/src/main/kotlin/geyser.build-logic.gradle.kts +++ /dev/null @@ -1,45 +0,0 @@ -repositories { - // mavenLocal() - - mavenCentral() - - // Floodgate, Cumulus etc. - maven("https://repo.opencollab.dev/main") - - // Paper, Velocity - maven("https://repo.papermc.io/repository/maven-public") - - // Spigot - maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots") { - mavenContent { snapshotsOnly() } - } - - // BungeeCord - maven("https://oss.sonatype.org/content/repositories/snapshots") { - mavenContent { snapshotsOnly() } - } - - // NeoForge - maven("https://maven.neoforged.net/releases") { - mavenContent { releasesOnly() } - } - - // Minecraft - maven("https://libraries.minecraft.net") { - name = "minecraft" - mavenContent { releasesOnly() } - } - - // ViaVersion - maven("https://repo.viaversion.com") { - name = "viaversion" - } - - // Jitpack for e.g. MCPL - maven("https://jitpack.io") { - content { includeGroupByRegex("com\\.github\\..*") } - } - - // For Adventure snapshots - maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") -} 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 8584c13d4..779d6446a 100644 --- a/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts @@ -2,11 +2,9 @@ import net.fabricmc.loom.task.RemapJarTask import org.gradle.kotlin.dsl.dependencies -import org.gradle.kotlin.dsl.maven plugins { - id("geyser.build-logic") - id("geyser.publish-conventions") + id("geyser.platform-conventions") id("architectury-plugin") id("dev.architectury.loom") } diff --git a/build-logic/src/main/kotlin/geyser.platform-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.platform-conventions.gradle.kts index 410e67404..7a342783b 100644 --- a/build-logic/src/main/kotlin/geyser.platform-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.platform-conventions.gradle.kts @@ -1,3 +1,20 @@ plugins { id("geyser.publish-conventions") -} \ No newline at end of file + id("io.freefair.lombok") +} + +tasks { + processResources { + // Spigot, BungeeCord, Velocity, Fabric, ViaProxy, NeoForge + 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", + "version" to project.version, + "description" to project.description, + "url" to "https://geysermc.org", + "author" to "GeyserMC" + ) + } + } +} diff --git a/build.gradle.kts b/build.gradle.kts index dfbf9837f..7f700a2f6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,55 +1,5 @@ plugins { - `java-library` // Ensure AP works in eclipse (no effect on other IDEs) eclipse - id("geyser.build-logic") - alias(libs.plugins.lombok) apply false + id("geyser.base-conventions") } - -allprojects { - group = properties["group"] as String + "." + properties["id"] as String - version = properties["version"] as String - description = properties["description"] as String -} - -val basePlatforms = setOf( - projects.bungeecord, - projects.spigot, - projects.standalone, - projects.velocity, - projects.viaproxy -).map { it.dependencyProject } - -val moddedPlatforms = setOf( - projects.fabric, - projects.neoforge, - projects.mod -).map { it.dependencyProject } - -val modrinthPlatforms = setOf( - projects.bungeecord, - projects.fabric, - projects.neoforge, - projects.spigot, - projects.velocity -).map { it.dependencyProject } - -subprojects { - apply { - plugin("java-library") - plugin("io.freefair.lombok") - plugin("geyser.build-logic") - } - - when (this) { - in basePlatforms -> plugins.apply("geyser.platform-conventions") - in moddedPlatforms -> plugins.apply("geyser.modded-conventions") - else -> plugins.apply("geyser.base-conventions") - } - - // Not combined with platform-conventions as that also contains - // platforms which we cant publish to modrinth - if (modrinthPlatforms.contains(this)) { - plugins.apply("geyser.modrinth-uploading-conventions") - } -} \ No newline at end of file diff --git a/common/build.gradle.kts b/common/build.gradle.kts index efba08c8d..166ffe9f5 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -1,5 +1,6 @@ plugins { id("geyser.publish-conventions") + id("io.freefair.lombok") } dependencies { diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 8d022271b..d30e60298 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -3,6 +3,7 @@ plugins { idea alias(libs.plugins.blossom) id("geyser.publish-conventions") + id("io.freefair.lombok") } dependencies { diff --git a/gradle.properties b/gradle.properties index 814529d6c..dd1bc915a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,7 @@ # Gradle settings org.gradle.jvmargs=-Xmx4G org.gradle.daemon=false +org.gradle.configureondemand=true org.gradle.parallel=true org.gradle.caching=true org.gradle.vfs.watch=false diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c564720a3..f2a29ee74 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -134,6 +134,7 @@ protocol-connection = { group = "org.cloudburstmc.protocol", name = "bedrock-con math = { group = "org.cloudburstmc.math", name = "immutable", version = "2.0" } # plugins +lombok = { group = "io.freefair.gradle", name = "lombok-plugin", version.ref = "lombok" } 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" } @@ -141,7 +142,6 @@ architectury-loom = { group = "dev.architectury.loom", name = "dev.architectury. 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" } From 9dad34d0a82a7cb47b61016c15bb5e51dbcc2860 Mon Sep 17 00:00:00 2001 From: RK_01 <50594595+RaphiMC@users.noreply.github.com> Date: Tue, 3 Sep 2024 22:25:49 +0200 Subject: [PATCH 233/233] Unhardcode PARTICLES_DRAGON_BLOCK_BREAK id (#5018) --- .../protocol/java/level/JavaLevelEventTranslator.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) 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 f54de1b68..5b4ff1de7 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 @@ -291,10 +291,7 @@ public class JavaLevelEventTranslator extends PacketTranslator { - effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_GENERIC_SPAWN); - effectPacket.setData(65); - } + case PARTICLES_DRAGON_BLOCK_BREAK -> effectPacket.setType(ParticleType.DRAGON_DESTROY_BLOCK); case PARTICLES_WATER_EVAPORATING -> { effectPacket.setType(org.cloudburstmc.protocol.bedrock.data.LevelEvent.PARTICLE_EVAPORATE_WATER); effectPacket.setPosition(pos.add(-0.5f, 0.5f, -0.5f));