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 diff --git a/README.md b/README.md index 8eac49a24..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.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.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/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/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/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/connection/GeyserConnection.java b/api/src/main/java/org/geysermc/geyser/api/connection/GeyserConnection.java index 9bda4f903..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. 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/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/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/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..1564b7f75 100644 --- a/bootstrap/bungeecord/build.gradle.kts +++ b/bootstrap/bungeecord/build.gradle.kts @@ -1,5 +1,12 @@ +plugins { + id("geyser.platform-conventions") + id("geyser.modrinth-uploading-conventions") +} + dependencies { api(projects.core) + + implementation(libs.cloud.bungee) implementation(libs.adventure.text.serializer.bungeecord) compileOnlyApi(libs.bungeecord.proxy) } @@ -8,13 +15,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..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 @@ -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,19 +58,17 @@ 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; @Override @@ -99,10 +101,31 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { 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 (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 @@ -142,11 +165,6 @@ 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(); } // Force-disable query if enabled, or else Geyser won't enable @@ -181,16 +199,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 +234,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/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 0d083fcf7..56bec322e 100644 --- a/bootstrap/mod/fabric/build.gradle.kts +++ b/bootstrap/mod/fabric/build.gradle.kts @@ -1,5 +1,6 @@ plugins { - application + id("geyser.modded-conventions") + id("geyser.modrinth-uploading-conventions") } architectury { @@ -25,10 +26,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 @@ -38,13 +36,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") @@ -67,4 +64,4 @@ modrinth { dependencies { required.project("fabric-api") } -} \ No newline at end of file +} diff --git a/bootstrap/mod/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricBootstrap.java b/bootstrap/mod/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricBootstrap.java 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 e0e7c2dfa..4ab005b4f 100644 --- a/bootstrap/mod/neoforge/build.gradle.kts +++ b/bootstrap/mod/neoforge/build.gradle.kts @@ -1,16 +1,18 @@ plugins { - application + id("geyser.modded-conventions") + id("geyser.modrinth-uploading-conventions") } -// This is provided by "org.cloudburstmc.math.mutable" too, so yeet. -// NeoForge's class loader is *really* annoying. -provided("org.cloudburstmc.math", "api") - architectury { platformSetupLoomIde() neoForge() } +// 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 { @@ -37,10 +39,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 { @@ -56,4 +61,4 @@ tasks { modrinth { loaders.add("neoforge") uploadFile.set(tasks.getByPath("remapModrinthJar")) -} \ No newline at end of file +} diff --git a/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeBootstrap.java b/bootstrap/mod/neoforge/src/main/java/org/geysermc/geyser/platform/neoforge/GeyserNeoForgeBootstrap.java index b97e42389..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 @@ -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,26 @@ 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); + // An auxiliary listener for registering undefined permissions belonging to commands. See javadocs for more info. + NeoForge.EVENT_BUS.addListener(EventPriority.LOWEST, registry::onPermissionGatherForUndefined); } private void onServerStarted(ServerStartedEvent event) { @@ -87,13 +112,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..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 @@ -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,13 +86,14 @@ 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() { + // "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; @@ -130,50 +123,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 +155,8 @@ public abstract class GeyserModBootstrap implements GeyserBootstrap { } @Override - public GeyserCommandManager getGeyserCommandManager() { - return geyserCommandManager; + public CommandRegistry getCommandRegistry() { + return commandRegistry; } @Override @@ -235,6 +184,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 +220,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..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) { @@ -17,12 +22,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 +38,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 { @@ -79,5 +86,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/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..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 @@ -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() ? @@ -120,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; } @@ -134,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; } } @@ -147,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; } @@ -165,31 +175,43 @@ 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); - } + // 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; } + // Register commands after Geyser initialization, but before the server starts. + 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 +249,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 +304,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 +373,8 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { } @Override - public GeyserCommandManager getGeyserCommandManager() { - return this.geyserCommandManager; + public CommandRegistry getCommandRegistry() { + return this.commandRegistry; } @Override @@ -494,4 +477,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/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..b210693c1 100644 --- a/bootstrap/standalone/build.gradle.kts +++ b/bootstrap/standalone/build.gradle.kts @@ -1,5 +1,10 @@ import com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer +plugins { + application + id("geyser.platform-conventions") +} + 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..05035e271 100644 --- a/bootstrap/velocity/build.gradle.kts +++ b/bootstrap/velocity/build.gradle.kts @@ -1,14 +1,22 @@ +plugins { + id("geyser.platform-conventions") + id("geyser.modrinth-uploading-conventions") +} + dependencies { annotationProcessor(libs.velocity.api) 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 +46,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 +82,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..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 @@ -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 @@ -106,19 +109,36 @@ 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 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; } this.geyserLogger.setDebug(geyserConfig.isDebugMode()); GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); - } else { - this.geyserCommandManager = new GeyserCommandManager(geyser); - this.geyserCommandManager.init(); } GeyserImpl.start(); @@ -129,22 +149,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 +183,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..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) @@ -8,12 +12,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..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 @@ -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,21 +132,36 @@ public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserBootst @Override public void onGeyserEnable() { - if (GeyserImpl.getInstance().isReloading()) { + // 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()) { 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); } + if (this.config.getRemote().authType() == AuthType.FLOODGATE) { + ViaProxy.getConfig().setPassthroughBungeecordPlayerInfo(true); + } } @Override @@ -166,8 +185,8 @@ public class GeyserViaProxyPlugin extends ViaProxyPlugin implements GeyserBootst } @Override - public GeyserCommandManager getGeyserCommandManager() { - return this.commandManager; + public CommandRegistry getCommandRegistry() { + return this.commandRegistry; } @Override @@ -185,7 +204,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 +228,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/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/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/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.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 e69de29bb..000000000 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..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,10 +2,9 @@ import net.fabricmc.loom.task.RemapJarTask import org.gradle.kotlin.dsl.dependencies -import org.gradle.kotlin.dsl.maven plugins { - id("geyser.publish-conventions") + id("geyser.platform-conventions") id("architectury-plugin") id("dev.architectury.loom") } @@ -37,6 +36,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 } @@ -82,7 +85,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("") } } @@ -112,12 +115,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") -} \ 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 index d710ae1a2..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,11 +8,12 @@ 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.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/build-logic/src/main/kotlin/geyser.platform-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.platform-conventions.gradle.kts index 81d224906..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,4 +1,20 @@ plugins { - application 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/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(); diff --git a/core/build.gradle.kts b/core/build.gradle.kts index b8ae8d757..b0ea5fdf6 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 { @@ -51,6 +52,9 @@ dependencies { // Adventure text serialization api(libs.bundles.adventure) + // command library + api(libs.cloud.core) + api(libs.erosion.common) { isTransitive = false } @@ -101,9 +105,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() } @@ -137,7 +138,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)" } } 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..bc6108abf 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -62,13 +62,14 @@ 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; 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 +129,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) @@ -155,12 +156,6 @@ public class GeyserImpl implements GeyserApi { 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; @@ -231,9 +226,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 +259,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(); @@ -367,22 +363,6 @@ public class GeyserImpl implements GeyserApi { } } - String broadcastPort = System.getProperty("geyserBroadcastPort", ""); - if (!broadcastPort.isEmpty()) { - int parsedPort; - try { - parsedPort = Integer.parseInt(broadcastPort); - if (parsedPort < 1 || parsedPort > 65535) { - throw new NumberFormatException("The broadcast port must be between 1 and 65535 inclusive!"); - } - } catch (NumberFormatException e) { - logger.error(String.format("Invalid broadcast port: %s! Defaulting to configured port.", broadcastPort + " (" + e.getMessage() + ")")); - parsedPort = config.getBedrock().port(); - } - config.getBedrock().setBroadcastPort(parsedPort); - logger.info("Broadcast port set from system property: " + parsedPort); - } - if (platformType != PlatformType.VIAPROXY) { boolean floodgatePresent = bootstrap.testFloodgatePluginPresent(); if (config.getRemote().authType() == AuthType.FLOODGATE && !floodgatePresent) { @@ -397,6 +377,26 @@ public class GeyserImpl implements GeyserApi { } } + // 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")) { @@ -433,24 +433,27 @@ public class GeyserImpl implements GeyserApi { 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()))); + 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) { + 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 { - 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)); - } + logger.info(GeyserLocale.getLocaleStringLog("geyser.core.start", address, port)); } - }).join(); - } + } else { + 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)); + } + } + }).join(); if (config.getRemote().authType() == AuthType.FLOODGATE) { try { @@ -730,7 +733,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 +770,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..54681abea --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/command/CommandRegistry.java @@ -0,0 +1,302 @@ +/* + * 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.PingCommand; +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")); + 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")); + } + + 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..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 @@ -29,42 +29,70 @@ 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; - } + 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; @@ -75,25 +103,28 @@ 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 { + 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) { - 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 +132,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 +154,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/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/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/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)); 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/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(); + } } 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 3b543a943..1e050c840 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 @@ -54,7 +54,7 @@ public enum GeyserAttributeType { // Bedrock Attributes ABSORPTION(null, "minecraft:absorption", 0f, 1024f, 0f), - EXHAUSTION(null, "minecraft:player.exhaustion", 0f, 5f, 0f), + EXHAUSTION(null, "minecraft:player.exhaustion", 0f, 20f, 0f), EXPERIENCE(null, "minecraft:player.experience", 0f, 1f, 0f), EXPERIENCE_LEVEL(null, "minecraft:player.level", 0f, 24791.00f, 0f), HEALTH(null, "minecraft:health", 0f, 1024f, 20f), 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 518c2bf78..626ceca5c 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 @@ -46,6 +46,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; @@ -77,6 +78,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; @@ -115,6 +117,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); } @@ -302,6 +308,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. */ @@ -336,6 +372,7 @@ public class LivingEntity extends Entity { armorEquipmentPacket.setChestplate(chestplate); armorEquipmentPacket.setLeggings(leggings); armorEquipmentPacket.setBoots(boots); + armorEquipmentPacket.setBody(body); session.sendUpstreamPacket(armorEquipmentPacket); } @@ -414,9 +451,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/PlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java index 475b37d48..e3214879a 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 @@ -43,7 +43,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.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinitions; @@ -286,7 +290,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 dc0545cee..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 @@ -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(); @@ -128,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); } /** @@ -315,13 +327,24 @@ 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(); } 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/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/erosion/ErosionCancellationException.java b/core/src/main/java/org/geysermc/geyser/erosion/ErosionCancellationException.java new file mode 100644 index 000000000..ae283895b --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/erosion/ErosionCancellationException.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.erosion; + +import java.io.Serial; +import java.util.concurrent.CancellationException; + +public class ErosionCancellationException extends CancellationException { + @Serial + private static final long serialVersionUID = 1L; +} diff --git a/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundHandshakePacketHandler.java b/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundHandshakePacketHandler.java index 0b4f03643..88a7e0cd3 100644 --- a/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundHandshakePacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundHandshakePacketHandler.java @@ -42,7 +42,6 @@ public final class GeyserboundHandshakePacketHandler extends AbstractGeyserbound public void handleHandshake(GeyserboundHandshakePacket packet) { boolean useTcp = packet.getTransportType().getSocketAddress() == null; GeyserboundPacketHandlerImpl handler = new GeyserboundPacketHandlerImpl(session, useTcp ? new GeyserErosionPacketSender(session) : new NettyPacketSender<>()); - session.setErosionHandler(handler); if (!useTcp) { if (session.getGeyser().getErosionUnixListener() == null) { session.disconnect("Erosion configurations using Unix socket handling are not supported on this hardware!"); @@ -52,6 +51,7 @@ public final class GeyserboundHandshakePacketHandler extends AbstractGeyserbound } else { handler.onConnect(); } + session.setErosionHandler(handler); session.ensureInEventLoop(() -> session.getChunkCache().clear()); } 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 c8cbe384b..7202db449 100644 --- a/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java +++ b/core/src/main/java/org/geysermc/geyser/erosion/GeyserboundPacketHandlerImpl.java @@ -171,10 +171,10 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke @Override public void handleHandshake(GeyserboundHandshakePacket packet) { - this.close(); var handler = new GeyserboundHandshakePacketHandler(this.session); session.setErosionHandler(handler); handler.handleHandshake(packet); + this.close(); } @Override @@ -198,6 +198,17 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke public void close() { this.packetSender.close(); + + if (pendingLookup != null) { + pendingLookup.completeExceptionally(new ErosionCancellationException()); + } + if (pendingBatchLookup != null) { + pendingBatchLookup.completeExceptionally(new ErosionCancellationException()); + } + if (pickBlockLookup != null) { + pickBlockLookup.completeExceptionally(new ErosionCancellationException()); + } + asyncPendingLookups.forEach(($, future) -> future.completeExceptionally(new ErosionCancellationException())); } public int getNextTransactionId() { 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/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/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/impl/camera/CameraDefinitions.java b/core/src/main/java/org/geysermc/geyser/impl/camera/CameraDefinitions.java index 80564bdf3..1cf6a794e 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(), null, OptionalBoolean.empty(), null), + new CameraPreset(CameraPerspective.FREE.id(), "", null, null, null, null, null, null, OptionalBoolean.empty(), null, OptionalBoolean.empty(), null), + new CameraPreset(CameraPerspective.THIRD_PERSON.id(), "", null, null, null, null, null, null, OptionalBoolean.empty(), null, OptionalBoolean.empty(), null), + new CameraPreset(CameraPerspective.THIRD_PERSON_FRONT.id(), "", null, null, null, null, null, null, OptionalBoolean.empty(), null, OptionalBoolean.empty(), null), + new CameraPreset("geyser:free_audio", "minecraft:free", null, null, null, null, null, CameraAudioListener.PLAYER, OptionalBoolean.empty(), null, OptionalBoolean.of(false), null), + new CameraPreset("geyser:free_effects", "minecraft:free", null, null, null, null, null, CameraAudioListener.CAMERA, OptionalBoolean.empty(), null, OptionalBoolean.of(true), null), + new CameraPreset("geyser:free_audio_effects", "minecraft:free", null, null, null, null, null, CameraAudioListener.PLAYER, OptionalBoolean.empty(), null, OptionalBoolean.of(true), null)); SimpleDefinitionRegistry.Builder builder = SimpleDefinitionRegistry.builder(); for (int i = 0; i < CAMERA_PRESETS.size(); i++) { 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/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/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/inventory/updater/AnvilInventoryUpdater.java b/core/src/main/java/org/geysermc/geyser/inventory/updater/AnvilInventoryUpdater.java index 7afd31cc9..2e0c75708 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 @@ -32,6 +32,8 @@ import net.kyori.adventure.text.Component; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; +import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; +import org.cloudburstmc.protocol.bedrock.data.inventory.FullContainerName; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; import org.geysermc.geyser.GeyserImpl; @@ -78,6 +80,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater { slotPacket.setContainerId(ContainerId.UI); slotPacket.setSlot(bedrockSlot); slotPacket.setItem(inventory.getItem(i).getItemData(session)); + slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(slotPacket); } } @@ -98,6 +101,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater { slotPacket.setContainerId(ContainerId.UI); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session)); + slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(slotPacket); } else if (lastTargetSlot != javaSlot) { // Update the previous target slot to remove repair cost changes @@ -105,6 +109,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater { slotPacket.setContainerId(ContainerId.UI); slotPacket.setSlot(translator.javaSlotToBedrock(lastTargetSlot)); slotPacket.setItem(inventory.getItem(lastTargetSlot).getItemData(session)); + slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(slotPacket); } @@ -168,6 +173,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater { slotPacket.setContainerId(ContainerId.UI); slotPacket.setSlot(translator.javaSlotToBedrock(slot)); slotPacket.setItem(itemData); + slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(slotPacket); } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/updater/ChestInventoryUpdater.java b/core/src/main/java/org/geysermc/geyser/inventory/updater/ChestInventoryUpdater.java index 5d6214871..9f3d00c57 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/updater/ChestInventoryUpdater.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/updater/ChestInventoryUpdater.java @@ -25,6 +25,8 @@ package org.geysermc.geyser.inventory.updater; +import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; +import org.cloudburstmc.protocol.bedrock.data.inventory.FullContainerName; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket; import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; @@ -61,6 +63,7 @@ public class ChestInventoryUpdater extends InventoryUpdater { InventoryContentPacket contentPacket = new InventoryContentPacket(); contentPacket.setContainerId(inventory.getBedrockId()); contentPacket.setContents(bedrockItems); + contentPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(contentPacket); } @@ -73,6 +76,7 @@ public class ChestInventoryUpdater extends InventoryUpdater { slotPacket.setContainerId(inventory.getBedrockId()); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session)); + slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(slotPacket); return true; } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/updater/ContainerInventoryUpdater.java b/core/src/main/java/org/geysermc/geyser/inventory/updater/ContainerInventoryUpdater.java index c9f313f2a..3d372c083 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/updater/ContainerInventoryUpdater.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/updater/ContainerInventoryUpdater.java @@ -25,6 +25,8 @@ package org.geysermc.geyser.inventory.updater; +import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; +import org.cloudburstmc.protocol.bedrock.data.inventory.FullContainerName; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket; import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; @@ -49,6 +51,7 @@ public class ContainerInventoryUpdater extends InventoryUpdater { InventoryContentPacket contentPacket = new InventoryContentPacket(); contentPacket.setContainerId(inventory.getBedrockId()); contentPacket.setContents(Arrays.asList(bedrockItems)); + contentPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(contentPacket); } @@ -61,6 +64,7 @@ public class ContainerInventoryUpdater extends InventoryUpdater { slotPacket.setContainerId(inventory.getBedrockId()); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session)); + slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(slotPacket); return true; } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/updater/CrafterInventoryUpdater.java b/core/src/main/java/org/geysermc/geyser/inventory/updater/CrafterInventoryUpdater.java index 4474d420c..315b84c6d 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/updater/CrafterInventoryUpdater.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/updater/CrafterInventoryUpdater.java @@ -26,6 +26,8 @@ package org.geysermc.geyser.inventory.updater; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; +import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; +import org.cloudburstmc.protocol.bedrock.data.inventory.FullContainerName; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket; import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; @@ -56,6 +58,7 @@ public class CrafterInventoryUpdater extends InventoryUpdater { contentPacket = new InventoryContentPacket(); contentPacket.setContainerId(inventory.getBedrockId()); contentPacket.setContents(Arrays.asList(bedrockItems)); + contentPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(contentPacket); // inventory and hotbar @@ -67,6 +70,7 @@ public class CrafterInventoryUpdater extends InventoryUpdater { contentPacket = new InventoryContentPacket(); contentPacket.setContainerId(ContainerId.INVENTORY); contentPacket.setContents(Arrays.asList(bedrockItems)); + contentPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(contentPacket); // Crafter result - it doesn't come after the grid, as explained elsewhere. @@ -88,6 +92,7 @@ public class CrafterInventoryUpdater extends InventoryUpdater { packet.setContainerId(containerId); packet.setSlot(translator.javaSlotToBedrock(javaSlot)); packet.setItem(inventory.getItem(javaSlot).getItemData(session)); + packet.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(packet); return true; } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/updater/HorseInventoryUpdater.java b/core/src/main/java/org/geysermc/geyser/inventory/updater/HorseInventoryUpdater.java index 7441e66d0..1a46fc02a 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/updater/HorseInventoryUpdater.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/updater/HorseInventoryUpdater.java @@ -25,6 +25,8 @@ package org.geysermc.geyser.inventory.updater; +import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; +import org.cloudburstmc.protocol.bedrock.data.inventory.FullContainerName; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket; import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; @@ -49,6 +51,7 @@ public class HorseInventoryUpdater extends InventoryUpdater { InventoryContentPacket contentPacket = new InventoryContentPacket(); contentPacket.setContainerId(inventory.getBedrockId()); contentPacket.setContents(Arrays.asList(bedrockItems)); + contentPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(contentPacket); } @@ -61,6 +64,7 @@ public class HorseInventoryUpdater extends InventoryUpdater { slotPacket.setContainerId(4); // Horse GUI? slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session)); + slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(slotPacket); return true; } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/updater/InventoryUpdater.java b/core/src/main/java/org/geysermc/geyser/inventory/updater/InventoryUpdater.java index 68ee334ba..b7ef4720f 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/updater/InventoryUpdater.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/updater/InventoryUpdater.java @@ -26,6 +26,8 @@ package org.geysermc.geyser.inventory.updater; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; +import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; +import org.cloudburstmc.protocol.bedrock.data.inventory.FullContainerName; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket; import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; @@ -45,6 +47,7 @@ public class InventoryUpdater { InventoryContentPacket contentPacket = new InventoryContentPacket(); contentPacket.setContainerId(ContainerId.INVENTORY); contentPacket.setContents(Arrays.asList(bedrockItems)); + contentPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(contentPacket); } @@ -54,6 +57,7 @@ public class InventoryUpdater { slotPacket.setContainerId(ContainerId.INVENTORY); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session)); + slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(slotPacket); return true; } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/updater/UIInventoryUpdater.java b/core/src/main/java/org/geysermc/geyser/inventory/updater/UIInventoryUpdater.java index a23385b53..f4f40d6ce 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/updater/UIInventoryUpdater.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/updater/UIInventoryUpdater.java @@ -26,6 +26,8 @@ package org.geysermc.geyser.inventory.updater; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; +import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; +import org.cloudburstmc.protocol.bedrock.data.inventory.FullContainerName; import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.session.GeyserSession; @@ -46,6 +48,7 @@ public class UIInventoryUpdater extends InventoryUpdater { slotPacket.setContainerId(ContainerId.UI); slotPacket.setSlot(bedrockSlot); slotPacket.setItem(inventory.getItem(i).getItemData(session)); + slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(slotPacket); } } @@ -59,6 +62,7 @@ public class UIInventoryUpdater extends InventoryUpdater { slotPacket.setContainerId(ContainerId.UI); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session)); + slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(slotPacket); return true; } 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 3c0caa60c..301f69a5f 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,8 +25,7 @@ package org.geysermc.geyser.item.enchantment; -import java.util.List; -import java.util.function.Function; +import it.unimi.dsi.fastutil.ints.IntArrays; import net.kyori.adventure.key.Key; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtMap; @@ -35,11 +34,14 @@ 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.item.component.HolderSet; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; -import org.geysermc.mcprotocollib.protocol.data.game.item.component.HolderSet; +import java.util.function.ToIntFunction; /** * @param description only populated if {@link #bedrockEnchantment()} is not null. @@ -69,7 +71,7 @@ public record Enchantment(String identifier, // 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; + String description = bedrockEnchantment == null ? MessageTranslator.deserializeDescription(context.session(), data) : null; return new Enchantment(context.id().asString(), effects, supportedItems, maxLevel, description, anvilCost, exclusiveSet, bedrockEnchantment); @@ -86,21 +88,21 @@ public record Enchantment(String identifier, } // TODO holder set util? - private static HolderSet readHolderSet(@Nullable Object holderSet, Function keyIdMapping) { + private static HolderSet readHolderSet(@Nullable Object holderSet, ToIntFunction keyIdMapping) { if (holderSet == null) { - return new HolderSet(new int[]{}); + return new HolderSet(IntArrays.EMPTY_ARRAY); } if (holderSet instanceof String stringTag) { // Tag if (stringTag.startsWith("#")) { - return new HolderSet(Key.key(stringTag.substring(1))); // Remove '#' at beginning that indicates tag + return new HolderSet(MinecraftKey.key(stringTag.substring(1))); // Remove '#' at beginning that indicates tag } else { - return new HolderSet(new int[]{keyIdMapping.apply(Key.key(stringTag))}); + return new HolderSet(new int[]{keyIdMapping.applyAsInt(MinecraftKey.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()); + return new HolderSet(list.stream().map(o -> (String) o).map(Key::key).mapToInt(keyIdMapping).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/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/level/GeyserWorldManager.java b/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java index 9faa7424c..befcfa4b7 100644 --- a/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java +++ b/core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java @@ -35,6 +35,7 @@ import org.geysermc.erosion.packet.backendbound.BackendboundBatchBlockRequestPac import org.geysermc.erosion.packet.backendbound.BackendboundBlockRequestPacket; import org.geysermc.erosion.packet.backendbound.BackendboundPickBlockPacket; import org.geysermc.erosion.util.BlockPositionIterator; +import org.geysermc.geyser.erosion.ErosionCancellationException; 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; @@ -49,6 +50,8 @@ public class GeyserWorldManager extends WorldManager { var erosionHandler = session.getErosionHandler().getAsActive(); if (erosionHandler == null) { return session.getChunkCache().getBlockAt(x, y, z); + } else if (session.isClosed()) { + throw new ErosionCancellationException(); } CompletableFuture future = new CompletableFuture<>(); // Boxes erosionHandler.setPendingLookup(future); @@ -61,6 +64,8 @@ public class GeyserWorldManager extends WorldManager { var erosionHandler = session.getErosionHandler().getAsActive(); if (erosionHandler == null) { return super.getBlockAtAsync(session, x, y, z); + } else if (session.isClosed()) { + return CompletableFuture.failedFuture(new ErosionCancellationException()); } CompletableFuture future = new CompletableFuture<>(); // Boxes int transactionId = erosionHandler.getNextTransactionId(); @@ -74,6 +79,8 @@ public class GeyserWorldManager extends WorldManager { var erosionHandler = session.getErosionHandler().getAsActive(); if (erosionHandler == null) { return super.getBlocksAt(session, iter); + } else if (session.isClosed()) { + throw new ErosionCancellationException(); } CompletableFuture future = new CompletableFuture<>(); erosionHandler.setPendingBatchLookup(future); @@ -118,17 +125,14 @@ 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) { var erosionHandler = session.getErosionHandler().getAsActive(); if (erosionHandler == null) { return super.getPickItemComponents(session, x, y, z, addNbtData); + } else if (session.isClosed()) { + return CompletableFuture.failedFuture(new ErosionCancellationException()); } CompletableFuture> future = new CompletableFuture<>(); erosionHandler.setPickBlockLookup(future); 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..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,8 +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(); @@ -45,8 +50,10 @@ 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.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!!! @@ -64,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/JukeboxSong.java b/core/src/main/java/org/geysermc/geyser/level/JukeboxSong.java index b00dc9f98..86d66e209 100644 --- a/core/src/main/java/org/geysermc/geyser/level/JukeboxSong.java +++ b/core/src/main/java/org/geysermc/geyser/level/JukeboxSong.java @@ -44,7 +44,7 @@ public record JukeboxSong(String soundEvent, String description) { soundEvent = ""; 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); + String description = MessageTranslator.deserializeDescription(context.session(), data); return new JukeboxSong(soundEvent, description); } } 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/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/network/CodecProcessor.java b/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java index e7cf81d47..741369c46 100644 --- a/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java +++ b/core/src/main/java/org/geysermc/geyser/network/CodecProcessor.java @@ -33,13 +33,17 @@ import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.MobArmorEquipment import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.MobEquipmentSerializer_v291; import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.PlayerHotbarSerializer_v291; import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.SetEntityLinkSerializer_v291; -import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.SetEntityMotionSerializer_v291; import org.cloudburstmc.protocol.bedrock.codec.v390.serializer.PlayerSkinSerializer_v390; import org.cloudburstmc.protocol.bedrock.codec.v407.serializer.InventoryContentSerializer_v407; import org.cloudburstmc.protocol.bedrock.codec.v407.serializer.InventorySlotSerializer_v407; 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.codec.v729.serializer.InventoryContentSerializer_v729; +import org.cloudburstmc.protocol.bedrock.codec.v729.serializer.InventorySlotSerializer_v729; import org.cloudburstmc.protocol.bedrock.packet.AnvilDamagePacket; import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket; import org.cloudburstmc.protocol.bedrock.packet.BossEventPacket; @@ -119,7 +123,24 @@ 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!"); + } + }; + + private static final BedrockPacketSerializer INVENTORY_CONTENT_SERIALIZER_V729 = new InventoryContentSerializer_v729() { @Override public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, InventoryContentPacket packet) { throw new IllegalArgumentException("Client cannot send InventoryContentPacket in server-auth inventory environment!"); @@ -129,7 +150,24 @@ 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!"); + } + }; + + private static final BedrockPacketSerializer INVENTORY_SLOT_SERIALIZER_V729 = new InventorySlotSerializer_v729() { @Override public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, InventorySlotPacket packet) { throw new IllegalArgumentException("Client cannot send InventorySlotPacket in server-auth inventory environment!"); @@ -148,7 +186,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) { } @@ -182,18 +229,9 @@ class CodecProcessor { }; /** - * Serializer that does nothing when trying to deserialize SetEntityMotionPacket since it is not used from the client for codec v291. + * Serializer that does nothing when trying to deserialize SetEntityMotionPacket since it is not used from the client. */ - private static final BedrockPacketSerializer SET_ENTITY_MOTION_SERIALIZER_V291 = new SetEntityMotionSerializer_v291() { - @Override - public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, SetEntityMotionPacket packet) { - } - }; - - /** - * Serializer that does nothing when trying to deserialize SetEntityMotionPacket since it is not used from the client for codec v662. - */ - private static final BedrockPacketSerializer SET_ENTITY_MOTION_SERIALIZER_V662 = new SetEntityMotionSerializer_v662() { + private static final BedrockPacketSerializer SET_ENTITY_MOTION_SERIALIZER = new SetEntityMotionSerializer_v662() { @Override public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, SetEntityMotionPacket packet) { } @@ -224,6 +262,27 @@ class CodecProcessor { @SuppressWarnings("unchecked") static BedrockCodec processCodec(BedrockCodec codec) { + boolean is729OrAbove = codec.getProtocolVersion() >= 729; + boolean is712OrAbove = codec.getProtocolVersion() >= 712; + + BedrockPacketSerializer inventoryContentSerializer; + if (is729OrAbove) { + inventoryContentSerializer = INVENTORY_CONTENT_SERIALIZER_V729; + } else if (is712OrAbove) { + inventoryContentSerializer = INVENTORY_CONTENT_SERIALIZER_V712; + } else { + inventoryContentSerializer = INVENTORY_CONTENT_SERIALIZER_V407; + } + + BedrockPacketSerializer inventorySlotSerializer; + if (is729OrAbove) { + inventorySlotSerializer = INVENTORY_SLOT_SERIALIZER_V729; + } else if (is712OrAbove) { + inventorySlotSerializer = INVENTORY_SLOT_SERIALIZER_V712; + } else { + inventorySlotSerializer = INVENTORY_SLOT_SERIALIZER_V407; + } + BedrockCodec.Builder codecBuilder = codec.toBuilder() // Illegal unused serverbound EDU packets .updateSerializer(PhotoTransferPacket.class, ILLEGAL_SERIALIZER) @@ -252,15 +311,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, inventoryContentSerializer) + .updateSerializer(InventorySlotPacket.class, inventorySlotSerializer) // Ignored only when serverbound .updateSerializer(BossEventPacket.class, BOSS_EVENT_SERIALIZER) - .updateSerializer(MobArmorEquipmentPacket.class, MOB_ARMOR_EQUIPMENT_SERIALIZER) + .updateSerializer(MobArmorEquipmentPacket.class, is712OrAbove ? MOB_ARMOR_EQUIPMENT_SERIALIZER_V712 : MOB_ARMOR_EQUIPMENT_SERIALIZER_V291) .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..d3abf934f 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,9 @@ 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.codec.v729.Bedrock_v729; import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodec; @@ -43,17 +46,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_v729.CODEC.toBuilder() + .minecraftVersion("1.21.30") + .build()); /** * A list of all supported Bedrock versions that can join Geyser @@ -73,9 +72,13 @@ 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() + SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v686.CODEC.toBuilder() .minecraftVersion("1.21.2/1.21.3") - .build()); + .build())); + SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v712.CODEC.toBuilder() + .minecraftVersion("1.21.20 - 1.21.23") + .build())); + SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC); } /** @@ -98,6 +101,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/network/UpstreamPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java index f56a8a43f..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; @@ -120,10 +119,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 { @@ -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/network/netty/GeyserServer.java b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java index a67bd8a32..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 @@ -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; @@ -143,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(); } @@ -316,7 +312,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 +363,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 +386,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. */ diff --git a/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java index 9a5b43816..b31f2b4f0 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java +++ b/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java @@ -31,6 +31,7 @@ import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.Clien import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundLightUpdatePacket; import io.netty.channel.EventLoop; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.erosion.ErosionCancellationException; import org.geysermc.geyser.registry.loader.RegistryLoaders; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; @@ -87,6 +88,8 @@ public class PacketTranslatorRegistry extends AbstractMappedRegistry, 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/registry/populator/BlockRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java index f539e52ec..bface58da 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java @@ -34,10 +34,20 @@ 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.nbt.*; +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.ObjectIntPair; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.cloudburstmc.nbt.NBTInputStream; +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.codec.v712.Bedrock_v712; +import org.cloudburstmc.protocol.bedrock.codec.v729.Bedrock_v729; import org.cloudburstmc.protocol.bedrock.data.BlockPropertyData; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.geysermc.geyser.GeyserImpl; @@ -61,7 +71,15 @@ 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.ArrayList; +import java.util.Arrays; +import java.util.BitSet; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; import java.util.stream.Stream; import java.util.zip.GZIPInputStream; @@ -108,7 +126,9 @@ 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()), Conversion729_712::remapBlock) + .put(ObjectIntPair.of("1_21_30", Bedrock_v729.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..db715e015 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion712_685.java @@ -0,0 +1,440 @@ +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) { + mapping = Conversion729_712.remapItem(item, 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) { + tag = Conversion729_712.remapBlock(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/Conversion729_712.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion729_712.java new file mode 100644 index 000000000..5d4ebdc47 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion729_712.java @@ -0,0 +1,151 @@ +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 Conversion729_712 { + private static final List NEW_PURPUR_BLOCKS = List.of("minecraft:purpur_block", "minecraft:purpur_pillar"); + private static final List NEW_WALL_BLOCKS = List.of("minecraft:cobblestone_wall", "minecraft:mossy_cobblestone_wall", "minecraft:granite_wall", "minecraft:diorite_wall", "minecraft:andesite_wall", "minecraft:sandstone_wall", "minecraft:brick_wall", "minecraft:stone_brick_wall", "minecraft:mossy_stone_brick_wall", "minecraft:nether_brick_wall", "minecraft:end_stone_brick_wall", "minecraft:prismarine_wall", "minecraft:red_sandstone_wall", "minecraft:red_nether_brick_wall"); + private static final List NEW_SPONGE_BLOCKS = List.of("minecraft:sponge", "minecraft:wet_sponge"); + private static final List NEW_TNT_BLOCKS = List.of("minecraft:tnt", "minecraft:underwater_tnt"); + private static final List STRUCTURE_VOID = List.of("minecraft:structure_void"); + private static final List NEW_BLOCKS = Stream.of(NEW_PURPUR_BLOCKS, NEW_WALL_BLOCKS, NEW_SPONGE_BLOCKS, NEW_TNT_BLOCKS, STRUCTURE_VOID).flatMap(List::stream).toList(); + + static GeyserMappingItem remapItem(Item item, GeyserMappingItem mapping) { + String identifier = mapping.getBedrockIdentifier(); + + if (!NEW_BLOCKS.contains(identifier)) { + return mapping; + } + + if (identifier.equals("minecraft:underwater_tnt")) { + return mapping.withBedrockIdentifier("minecraft:tnt").withBedrockData(1); + } + + if (NEW_PURPUR_BLOCKS.contains(identifier)) { + switch (identifier) { + case "minecraft:purpur_block" -> { return mapping.withBedrockIdentifier("minecraft:purpur_block").withBedrockData(0); } + case "minecraft:purpur_pillar" -> { return mapping.withBedrockIdentifier("minecraft:purpur_block").withBedrockData(1); } + } + } + + if (NEW_WALL_BLOCKS.contains(identifier)) { + switch (identifier) { + case "minecraft:cobblestone_wall" -> { return mapping.withBedrockIdentifier("minecraft:cobblestone_wall").withBedrockData(0); } + case "minecraft:mossy_cobblestone_wall" -> { return mapping.withBedrockIdentifier("minecraft:cobblestone_wall").withBedrockData(1); } + case "minecraft:granite_wall" -> { return mapping.withBedrockIdentifier("minecraft:cobblestone_wall").withBedrockData(2); } + case "minecraft:diorite_wall" -> { return mapping.withBedrockIdentifier("minecraft:cobblestone_wall").withBedrockData(3); } + case "minecraft:andesite_wall" -> { return mapping.withBedrockIdentifier("minecraft:cobblestone_wall").withBedrockData(4); } + case "minecraft:sandstone_wall" -> { return mapping.withBedrockIdentifier("minecraft:cobblestone_wall").withBedrockData(5); } + case "minecraft:brick_wall" -> { return mapping.withBedrockIdentifier("minecraft:cobblestone_wall").withBedrockData(6); } + case "minecraft:stone_brick_wall" -> { return mapping.withBedrockIdentifier("minecraft:cobblestone_wall").withBedrockData(7); } + case "minecraft:mossy_stone_brick_wall" -> { return mapping.withBedrockIdentifier("minecraft:cobblestone_wall").withBedrockData(8); } + case "minecraft:nether_brick_wall" -> { return mapping.withBedrockIdentifier("minecraft:cobblestone_wall").withBedrockData(9); } + case "minecraft:end_stone_brick_wall" -> { return mapping.withBedrockIdentifier("minecraft:cobblestone_wall").withBedrockData(10); } + case "minecraft:prismarine_wall" -> { return mapping.withBedrockIdentifier("minecraft:cobblestone_wall").withBedrockData(11); } + case "minecraft:red_sandstone_wall" -> { return mapping.withBedrockIdentifier("minecraft:cobblestone_wall").withBedrockData(12); } + case "minecraft:red_nether_brick_wall" -> { return mapping.withBedrockIdentifier("minecraft:cobblestone_wall").withBedrockData(13); } + } + } + + if (NEW_SPONGE_BLOCKS.contains(identifier)) { + switch (identifier) { + case "minecraft:sponge" -> { return mapping.withBedrockIdentifier("minecraft:sponge").withBedrockData(0); } + case "minecraft:wet_sponge" -> { return mapping.withBedrockIdentifier("minecraft:sponge").withBedrockData(1); } + } + } + + return mapping; + } + + static NbtMap remapBlock(NbtMap tag) { + final String name = tag.getString("name"); + + if (!NEW_BLOCKS.contains(name)) { + return tag; + } + + String replacement; + + if (NEW_PURPUR_BLOCKS.contains(name)) { + replacement = "minecraft:purpur_block"; + String purpurType = name.equals("minecraft:purpur_pillar") ? "lines" : "default"; + + NbtMap states = tag.getCompound("states") + .toBuilder() + .putString("chisel_type", purpurType) + .build(); + + return tag.toBuilder().putString("name", replacement).putCompound("states", states).build(); + } + + if (NEW_WALL_BLOCKS.contains(name)) { + replacement = "minecraft:cobblestone_wall"; + String wallType; + + switch (name) { + case "minecraft:cobblestone_wall" -> wallType = "cobblestone"; + case "minecraft:mossy_cobblestone_wall" -> wallType = "mossy_cobblestone"; + case "minecraft:granite_wall" -> wallType = "granite"; + case "minecraft:diorite_wall" -> wallType = "diorite"; + case "minecraft:andesite_wall" -> wallType = "andesite"; + case "minecraft:sandstone_wall" -> wallType = "sandstone"; + case "minecraft:brick_wall" -> wallType = "brick"; + case "minecraft:stone_brick_wall" -> wallType = "stone_brick"; + case "minecraft:mossy_stone_brick_wall" -> wallType = "mossy_stone_brick"; + case "minecraft:nether_brick_wall" -> wallType = "nether_brick"; + case "minecraft:end_stone_brick_wall" -> wallType = "end_brick"; + case "minecraft:prismarine_wall" -> wallType = "prismarine"; + case "minecraft:red_sandstone_wall" -> wallType = "red_sandstone"; + case "minecraft:red_nether_brick_wall" -> wallType = "red_nether_brick"; + default -> throw new IllegalStateException("Unexpected value: " + name); + } + + NbtMap states = tag.getCompound("states") + .toBuilder() + .putString("wall_block_type", wallType) + .build(); + + return tag.toBuilder().putString("name", replacement).putCompound("states", states).build(); + } + + if (NEW_SPONGE_BLOCKS.contains(name)) { + replacement = "minecraft:sponge"; + String spongeType = name.equals("minecraft:wet_sponge") ? "wet" : "dry"; + + NbtMap states = tag.getCompound("states") + .toBuilder() + .putString("sponge_type", spongeType) + .build(); + + return tag.toBuilder().putString("name", replacement).putCompound("states", states).build(); + } + + if (NEW_TNT_BLOCKS.contains(name)) { + replacement = "minecraft:tnt"; + byte tntType = (byte) (name.equals("minecraft:underwater_tnt") ? 1 : 0); + + NbtMap states = tag.getCompound("states") + .toBuilder() + .putByte("allow_underwater_bit", tntType) + .build(); + + return tag.toBuilder().putString("name", replacement).putCompound("states", states).build(); + } + + if (STRUCTURE_VOID.contains(name)) { + NbtMap states = tag.getCompound("states") + .toBuilder() + .putString("structure_void_type", "air") + .build(); + + return tag.toBuilder().putCompound("states", states).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..bea213aa4 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,8 @@ 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.codec.v729.Bedrock_v729; 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 +92,9 @@ 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(), Collections.emptyMap(), Conversion729_712::remapItem)); + paletteVersions.add(new PaletteVersion("1_21_30", Bedrock_v729.CODEC.getProtocolVersion())); GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap(); @@ -169,6 +173,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(); 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..4589afe23 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.Getter; import lombok.Setter; import lombok.experimental.Accessors; import net.kyori.adventure.key.Key; +import net.raphimc.minecraftauth.responsehandler.exception.MinecraftRequestException; import net.raphimc.minecraftauth.step.java.StepMCProfile; import net.raphimc.minecraftauth.step.java.StepMCToken; import net.raphimc.minecraftauth.step.java.session.StepFullJavaSession; @@ -54,6 +55,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; @@ -64,6 +67,7 @@ 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.LevelEvent; import org.cloudburstmc.protocol.bedrock.data.PlayerPermission; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.data.SpawnBiomeType; @@ -77,11 +81,13 @@ 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; import org.cloudburstmc.protocol.bedrock.packet.GameRulesChangedPacket; import org.cloudburstmc.protocol.bedrock.packet.ItemComponentPacket; +import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEvent2Packet; import org.cloudburstmc.protocol.bedrock.packet.PlayStatusPacket; import org.cloudburstmc.protocol.bedrock.packet.SetTimePacket; @@ -125,7 +131,9 @@ 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.ErosionCancellationException; import org.geysermc.geyser.erosion.GeyserboundHandshakePacketHandler; import org.geysermc.geyser.impl.camera.CameraDefinitions; import org.geysermc.geyser.impl.camera.GeyserCameraData; @@ -135,8 +143,10 @@ 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.GameProtocol; import org.geysermc.geyser.network.netty.LocalSession; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.BlockMappings; @@ -222,6 +232,7 @@ import java.util.Queue; import java.util.Set; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; @@ -252,7 +263,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @NonNull @Setter - private AbstractGeyserboundPacketHandler erosionHandler; + private volatile AbstractGeyserboundPacketHandler erosionHandler; @Accessors(fluent = true) @Setter @@ -384,6 +395,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; @@ -554,16 +572,16 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { private float walkSpeed; /** - * Caches current rain status. + * Caches current rain strength. + * Value between 0 and 1. */ - @Setter - private boolean raining = false; + private float rainStrength = 0.0f; /** - * Caches current thunder status. + * Caches current thunder strength. + * Value between 0 and 1. */ - @Setter - private boolean thunder = false; + private float thunderStrength = 0.0f; /** * Stores a map of all statistics sent from the server. @@ -590,6 +608,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 */ @@ -850,7 +881,14 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { return task.getAuthentication().handle((result, ex) -> { if (ex != null) { geyser.getLogger().error("Failed to log in with Microsoft code!", ex); - disconnect(ex.toString()); + if (ex instanceof CompletionException ce + && ce.getCause() instanceof MinecraftRequestException mre + && mre.getResponse().getStatusCode() == 404) { + // Player is trying to join with a Microsoft account that doesn't have Java Edition purchased + disconnect(GeyserLocale.getPlayerLocaleString("geyser.network.remote.invalid_account", locale())); + } else { + disconnect(ex.toString()); + } return false; } @@ -1164,9 +1202,9 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { tickThread.cancel(false); } - erosionHandler.close(); - + // Mark session as closed before cancelling erosion futures closed = true; + erosionHandler.close(); } /** @@ -1187,6 +1225,8 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { eventLoop.execute(() -> { try { runnable.run(); + } catch (ErosionCancellationException e) { + geyser.getLogger().debug("Caught ErosionCancellationException"); } catch (Throwable e) { geyser.getLogger().error("Error thrown in " + this.bedrockUsername() + "'s event loop!", e); } @@ -1204,6 +1244,8 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { if (!closed) { runnable.run(); } + } catch (ErosionCancellationException e) { + geyser.getLogger().debug("Caught ErosionCancellationException"); } catch (Throwable e) { geyser.getLogger().error("Error thrown in " + this.bedrockUsername() + "'s event loop!", e); } @@ -1249,6 +1291,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(); @@ -1284,6 +1330,9 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { } catch (Throwable throwable) { throwable.printStackTrace(); } + + ticks++; + worldTicks++; } public void setAuthenticationData(AuthData authData) { @@ -1454,11 +1503,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. */ @@ -1528,7 +1594,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); @@ -1771,17 +1837,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(); /** @@ -1963,6 +2018,71 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { }; } + /** + * Sends a packet to update rain strength. + * Stops rain if strength is 0. + * + * @param strength value between 0 and 1 + */ + public void updateRain(float strength) { + boolean wasRaining = isRaining(); + this.rainStrength = strength; + + LevelEventPacket rainPacket = new LevelEventPacket(); + rainPacket.setType(isRaining() ? LevelEvent.START_RAINING : LevelEvent.STOP_RAINING); + rainPacket.setData((int) (strength * 65535)); + rainPacket.setPosition(Vector3f.ZERO); + sendUpstreamPacket(rainPacket); + + // Keep thunder in sync with rain when starting/stopping a storm + if ((wasRaining != isRaining()) && isThunder()) { + if (isRaining()) { + LevelEventPacket thunderPacket = new LevelEventPacket(); + thunderPacket.setType(LevelEvent.START_THUNDERSTORM); + thunderPacket.setData((int) (this.thunderStrength * 65535)); + thunderPacket.setPosition(Vector3f.ZERO); + sendUpstreamPacket(thunderPacket); + } else { + LevelEventPacket thunderPacket = new LevelEventPacket(); + thunderPacket.setType(LevelEvent.STOP_THUNDERSTORM); + thunderPacket.setData(0); + thunderPacket.setPosition(Vector3f.ZERO); + sendUpstreamPacket(thunderPacket); + } + } + } + + /** + * Sends a packet to update thunderstorm strength. + * Stops thunderstorm if strength is 0. + * + * @param strength value between 0 and 1 + */ + public void updateThunder(float strength) { + this.thunderStrength = strength; + + // Do not send thunder packet if not raining + // The bedrock client will start raining automatically when updating thunder strength + // https://github.com/GeyserMC/Geyser/issues/3679 + if (!isRaining()) { + return; + } + + LevelEventPacket thunderPacket = new LevelEventPacket(); + thunderPacket.setType(isThunder() ? LevelEvent.START_THUNDERSTORM : LevelEvent.STOP_THUNDERSTORM); + thunderPacket.setData((int) (strength * 65535)); + thunderPacket.setPosition(Vector3f.ZERO); + sendUpstreamPacket(thunderPacket); + } + + public boolean isRaining() { + return this.rainStrength > 0; + } + + public boolean isThunder() { + return this.thunderStrength > 0; + } + @Override public @NonNull String bedrockUsername() { return authData.name(); @@ -2092,6 +2212,19 @@ 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()); + } + + @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); } 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) { 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/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/RegistryCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/RegistryCache.java index a393d461d..4a4167f15 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 @@ -49,7 +49,7 @@ 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.text.ChatDecoration; import org.geysermc.geyser.translator.level.BiomeTranslator; import org.geysermc.geyser.util.MinecraftKey; import org.geysermc.mcprotocollib.protocol.MinecraftProtocol; @@ -78,7 +78,7 @@ public final class RegistryCache { private static final Map>> REGISTRIES = new HashMap<>(); static { - register("chat_type", cache -> cache.chatTypes, TextDecoration::readChatType); + register("chat_type", cache -> cache.chatTypes, ChatDecoration::readChatType); register("dimension_type", cache -> cache.dimensions, JavaDimension::read); register("enchantment", cache -> cache.enchantments, Enchantment::read); register("jukebox_song", cache -> cache.jukeboxSongs, JukeboxSong::read); 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/session/cache/WorldCache.java b/core/src/main/java/org/geysermc/geyser/session/cache/WorldCache.java index c7436fc28..5927963c0 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 @@ -35,6 +35,7 @@ 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.packet.SetTitlePacket; +import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.scoreboard.Scoreboard; import org.geysermc.geyser.scoreboard.ScoreboardUpdater.ScoreboardSession; import org.geysermc.geyser.session.GeyserSession; @@ -71,6 +72,8 @@ public final class WorldCache { @Setter private boolean editingSignOnFront; + private final Object2IntMap activeCooldowns = new Object2IntOpenHashMap<>(2); + public WorldCache(GeyserSession session) { this.session = session; this.scoreboard = new Scoreboard(session); @@ -200,4 +203,32 @@ public final class WorldCache { public String removeActiveRecord(Vector3i pos) { return this.activeRecords.remove(pos); } + + public void setCooldown(Item item, int ticks) { + if (ticks == 0) { + // As of Java 1.21 + this.activeCooldowns.removeInt(item); + return; + } + this.activeCooldowns.put(item, session.getTicks() + ticks); + } + + public boolean hasCooldown(Item item) { + return this.activeCooldowns.containsKey(item); + } + + public void tick() { + // Implementation note: technically we could empty the field during hasCooldown checks, + // but we don't want the cooldown field to balloon in size from overuse. + if (!this.activeCooldowns.isEmpty()) { + int ticks = session.getTicks(); + Iterator> it = Object2IntMaps.fastIterator(this.activeCooldowns); + while (it.hasNext()) { + Object2IntMap.Entry entry = it.next(); + if (entry.getIntValue() <= ticks) { + it.remove(); + } + } + } + } } 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/text/TextDecoration.java b/core/src/main/java/org/geysermc/geyser/text/ChatDecoration.java similarity index 74% rename from core/src/main/java/org/geysermc/geyser/text/TextDecoration.java rename to core/src/main/java/org/geysermc/geyser/text/ChatDecoration.java index 94aec22ef..fc7597cfd 100644 --- a/core/src/main/java/org/geysermc/geyser/text/TextDecoration.java +++ b/core/src/main/java/org/geysermc/geyser/text/ChatDecoration.java @@ -25,17 +25,19 @@ package org.geysermc.geyser.text; -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.geyser.session.cache.registry.RegistryEntryContext; +import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.mcprotocollib.protocol.data.game.chat.ChatType; import org.geysermc.mcprotocollib.protocol.data.game.chat.ChatTypeDecoration; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; -public record TextDecoration(String translationKey, List parameters, Style deserializedStyle) implements ChatTypeDecoration { +public record ChatDecoration(String translationKey, List parameters, Style deserializedStyle) implements ChatTypeDecoration { @Override public NbtMap style() { @@ -53,38 +55,22 @@ public record TextDecoration(String translationKey, List parameters, String translationKey = chat.getString("translation_key"); NbtMap styleTag = chat.getCompound("style"); - Style style = deserializeStyle(styleTag); + Style style = MessageTranslator.getStyleFromNbtMap(styleTag); List parameters = new ArrayList<>(); List parametersNbt = chat.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(new ChatDecoration(translationKey, parameters, style), null); } return new ChatType(null, null); } public static Style getStyle(ChatTypeDecoration decoration) { - if (decoration instanceof TextDecoration textDecoration) { - return textDecoration.deserializedStyle(); + if (decoration instanceof ChatDecoration chatDecoration) { + return chatDecoration.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); - if (color != null) { - builder.color(NamedTextColor.NAMES.value(color)); - } - //TODO implement the rest - boolean italic = styleTag.getBoolean("italic"); - if (italic) { - builder.decorate(net.kyori.adventure.text.format.TextDecoration.ITALIC); - } - } - return builder.build(); + return MessageTranslator.getStyleFromNbtMap(decoration.style()); } } 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); } } 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/inventory/InventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java index 4c426b410..3338d2e52 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.*; @@ -200,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()) { @@ -240,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 @@ -270,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); } @@ -291,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); } @@ -439,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)); @@ -535,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); } @@ -698,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); } @@ -835,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; } @@ -894,11 +981,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(), new FullContainerName(entry.getKey(), 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), new FullContainerName(ContainerSlotType.CURSOR, null))); return containerEntries; } @@ -952,4 +1039,4 @@ public abstract class InventoryTranslator { TRANSFER, DONE } -} \ No newline at end of file +} 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 21fe9ca21..685d51fc0 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 @@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.inventory; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; +import org.cloudburstmc.protocol.bedrock.data.inventory.FullContainerName; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequest; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData; @@ -139,6 +140,7 @@ public class OldSmithingTableTranslator extends AbstractBlockInventoryTranslator slotPacket.setContainerId(ContainerId.UI); slotPacket.setSlot(53); slotPacket.setItem(UPGRADE_TEMPLATE.apply(session.getUpstream().getProtocolVersion())); + slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(slotPacket); } } 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..a276e4750 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 @@ -30,6 +30,7 @@ import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; +import org.cloudburstmc.protocol.bedrock.data.inventory.FullContainerName; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequest; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData; @@ -83,6 +84,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { contents[i - 36] = inventory.getItem(i).getItemData(session); } inventoryContentPacket.setContents(Arrays.asList(contents)); + inventoryContentPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(inventoryContentPacket); // Armor @@ -99,12 +101,14 @@ public class PlayerInventoryTranslator extends InventoryTranslator { } } armorContentPacket.setContents(Arrays.asList(contents)); + armorContentPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(armorContentPacket); // Offhand InventoryContentPacket offhandPacket = new InventoryContentPacket(); offhandPacket.setContainerId(ContainerId.OFFHAND); offhandPacket.setContents(Collections.singletonList(inventory.getItem(45).getItemData(session))); + offhandPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(offhandPacket); } @@ -123,9 +127,10 @@ 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)); } + slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(slotPacket); } } @@ -162,11 +167,13 @@ public class PlayerInventoryTranslator extends InventoryTranslator { slotPacket.setSlot(slot + 27); } slotPacket.setItem(bedrockItem); + slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(slotPacket); } else if (slot == 45) { InventoryContentPacket offhandPacket = new InventoryContentPacket(); offhandPacket.setContainerId(ContainerId.OFFHAND); offhandPacket.setContents(Collections.singletonList(bedrockItem)); + offhandPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(offhandPacket); } } diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/horse/ChestedHorseInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/horse/ChestedHorseInventoryTranslator.java index f1a5723c8..ba3b7285e 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/horse/ChestedHorseInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/horse/ChestedHorseInventoryTranslator.java @@ -27,6 +27,7 @@ package org.geysermc.geyser.translator.inventory.horse; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; +import org.cloudburstmc.protocol.bedrock.data.inventory.FullContainerName; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData; import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket; @@ -94,6 +95,7 @@ public abstract class ChestedHorseInventoryTranslator extends AbstractHorseInven InventoryContentPacket contentPacket = new InventoryContentPacket(); contentPacket.setContainerId(ContainerId.INVENTORY); contentPacket.setContents(Arrays.asList(bedrockItems)); + contentPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(contentPacket); ItemData[] horseItems = new ItemData[chestSize + 1]; @@ -107,6 +109,7 @@ public abstract class ChestedHorseInventoryTranslator extends AbstractHorseInven InventoryContentPacket horseContentsPacket = new InventoryContentPacket(); horseContentsPacket.setContainerId(inventory.getBedrockId()); horseContentsPacket.setContents(Arrays.asList(horseItems)); + horseContentsPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(horseContentsPacket); } } 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; 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/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/BedrockInventoryTransactionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java index 1e4c82da1..6ae21067f 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 @@ -31,6 +31,7 @@ import org.cloudburstmc.math.vector.Vector3d; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; +import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; @@ -42,6 +43,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.transaction.LegacySetIte import org.cloudburstmc.protocol.bedrock.packet.ContainerOpenPacket; import org.cloudburstmc.protocol.bedrock.packet.InventoryTransactionPacket; import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; +import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.type.Entity; @@ -75,12 +77,15 @@ 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.Holder; import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.InteractAction; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerAction; import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.Instrument; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClickPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundInteractPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosRotPacket; @@ -373,6 +378,22 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator instrument = session.getPlayerInventory() + .getItemInHand() + .getComponent(DataComponentType.INSTRUMENT); + if (instrument != null && instrument.isId()) { + // BDS uses a LevelSoundEvent2Packet, but that doesn't work here... (as of 1.21.20) + LevelSoundEventPacket soundPacket = new LevelSoundEventPacket(); + soundPacket.setSound(SoundEvent.valueOf("GOAT_CALL_" + instrument.id())); + soundPacket.setPosition(session.getPlayerEntity().getPosition()); + soundPacket.setIdentifier("minecraft:player"); + soundPacket.setExtraData(-1); + session.sendUpstreamPacket(soundPacket); + } + } } } 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/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..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 @@ -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; @@ -76,6 +76,9 @@ public class JavaCommandsTranslator extends PacketTranslator commandData = new ArrayList<>(); IntSet commandNodes = new IntOpenHashSet(); @@ -151,8 +161,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(); @@ -172,6 +184,8 @@ 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 @@ -188,6 +202,15 @@ public class JavaCommandsTranslator extends PacketTranslator { + + @Override + public void translate(GeyserSession session, ClientboundStartConfigurationPacket packet) { + var erosionHandler = session.getErosionHandler(); + if (erosionHandler.isActive()) { + // Set new handler before closing + session.setErosionHandler(new GeyserboundHandshakePacketHandler(session)); + erosionHandler.close(); + } + } + + @Override + public boolean shouldExecuteInEventLoop() { + // Execute outside of event loop to cancel any pending erosion futures + return false; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSystemChatTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSystemChatTranslator.java index 0a0f2832c..27481aa26 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSystemChatTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaSystemChatTranslator.java @@ -25,8 +25,13 @@ package org.geysermc.geyser.translator.protocol.java; -import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundSystemChatPacket; +import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.TranslatableComponent; +import net.kyori.adventure.text.TranslationArgument; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.protocol.bedrock.data.LevelEvent; +import org.cloudburstmc.protocol.bedrock.packet.LevelEventGenericPacket; import org.cloudburstmc.protocol.bedrock.packet.TextPacket; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.ChatColor; @@ -34,18 +39,47 @@ import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.text.MessageTranslator; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundSystemChatPacket; @Translator(packet = ClientboundSystemChatPacket.class) public class JavaSystemChatTranslator 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. + Integer numPlayersSleeping = convertToInt(component.arguments().get(0)); + Integer totalPlayersNeeded = convertToInt(component.arguments().get(1)); + if (numPlayersSleeping != null && totalPlayersNeeded != null) { + 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); } } @@ -68,4 +102,19 @@ public class JavaSystemChatTranslator 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; 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 6c2e02cd3..3195a6536 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 @@ -30,6 +30,8 @@ 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.data.inventory.ContainerSlotType; +import org.cloudburstmc.protocol.bedrock.data.inventory.FullContainerName; import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket; import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket; import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; @@ -167,6 +169,7 @@ public class JavaEntityEventTranslator 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; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetPassengersTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetPassengersTranslator.java index 9895a248c..865ca0464 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetPassengersTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSetPassengersTranslator.java @@ -30,6 +30,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityLinkData; import org.cloudburstmc.protocol.bedrock.packet.SetEntityLinkPacket; import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.type.Entity; +import org.geysermc.geyser.entity.vehicle.ClientVehicle; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; @@ -55,6 +56,10 @@ public class JavaSetPassengersTranslator extends PacketTranslator { - // Strength of rainstorms and thunderstorms is a 0-1 float on Java, while on Bedrock it is a 0-65535 int - private static final int MAX_STORM_STRENGTH = 65535; - @Override public void translate(GeyserSession session, ClientboundGameEventPacket packet) { PlayerEntity entity = session.getPlayerEntity(); @@ -65,42 +60,20 @@ public class JavaGameEventTranslator extends PacketTranslator 0f; - LevelEventPacket changeRainPacket = new LevelEventPacket(); - changeRainPacket.setType(isCurrentlyRaining ? LevelEvent.START_RAINING : LevelEvent.STOP_RAINING); // This is the rain strength on LevelEventType.START_RAINING, but can be any value on LevelEventType.STOP_RAINING - changeRainPacket.setData((int) (rainStrength * MAX_STORM_STRENGTH)); - changeRainPacket.setPosition(Vector3f.ZERO); - session.sendUpstreamPacket(changeRainPacket); - session.setRaining(isCurrentlyRaining); + float rainStrength = ((RainStrengthValue) packet.getValue()).getStrength(); + session.updateRain(rainStrength); break; case THUNDER_STRENGTH: // See above, same process float thunderStrength = ((ThunderStrengthValue) packet.getValue()).getStrength(); - boolean isCurrentlyThundering = thunderStrength > 0f; - LevelEventPacket changeThunderPacket = new LevelEventPacket(); - changeThunderPacket.setType(isCurrentlyThundering ? LevelEvent.START_THUNDERSTORM : LevelEvent.STOP_THUNDERSTORM); - changeThunderPacket.setData((int) (thunderStrength * MAX_STORM_STRENGTH)); - changeThunderPacket.setPosition(Vector3f.ZERO); - session.sendUpstreamPacket(changeThunderPacket); - session.setThunder(isCurrentlyThundering); + session.updateThunder(thunderStrength); break; case CHANGE_GAMEMODE: GameMode gameMode = (GameMode) packet.getValue(); 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 b6bb1c0c6..0e5d19785 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelChunkWithLightTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelChunkWithLightTranslator.java @@ -99,7 +99,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator> 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/translator/protocol/java/level/JavaLevelEventTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelEventTranslator.java index c10cfa018..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(61); - } + 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)); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSetTimeTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSetTimeTranslator.java index 1e398ad9b..43ef0870a 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSetTimeTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSetTimeTranslator.java @@ -36,6 +36,8 @@ public class JavaSetTimeTranslator extends PacketTranslator parameters = chat.parameters(); List args = new ArrayList<>(3); - if (parameters.contains(TextDecoration.Parameter.TARGET)) { + if (parameters.contains(ChatDecoration.Parameter.TARGET)) { args.add(targetName); } - if (parameters.contains(TextDecoration.Parameter.SENDER)) { + if (parameters.contains(ChatDecoration.Parameter.SENDER)) { args.add(sender); } - if (parameters.contains(TextDecoration.Parameter.CONTENT)) { + if (parameters.contains(ChatDecoration.Parameter.CONTENT)) { args.add(message); } withDecoration.arguments(args); @@ -410,17 +414,92 @@ public class MessageTranslator { } /** - * Deserialize an NbtMap provided from a registry into a string. + * Deserialize an NbtMap with a description text component (usually provided from a registry) into a Bedrock-formatted 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 ""; + public static String deserializeDescription(GeyserSession session, NbtMap tag) { + Object description = tag.get("description"); + Component parsed = componentFromNbtTag(description); + return convertMessage(session, parsed); + } + + public static Component componentFromNbtTag(Object nbtTag) { + return componentFromNbtTag(nbtTag, Style.empty()); + } + + private static Component componentFromNbtTag(Object nbtTag, Style style) { + if (nbtTag instanceof String literal) { + return Component.text(literal).style(style); + } else if (nbtTag instanceof List list) { + return Component.join(JoinConfiguration.noSeparators(), componentsFromNbtList(list, style)); + } else if (nbtTag instanceof NbtMap map) { + Component component = null; + String text = map.getString("text", null); + if (text != null) { + component = Component.text(text); + } else { + String translateKey = map.getString("translate", null); + if (translateKey != null) { + String fallback = map.getString("fallback", ""); + List args = new ArrayList<>(); + + Object with = map.get("with"); + if (with instanceof List list) { + args = componentsFromNbtList(list, style); + } else if (with != null) { + args.add(componentFromNbtTag(with, style)); + } + component = Component.translatable(translateKey, fallback, args); + } + } + + if (component != null) { + Style newStyle = getStyleFromNbtMap(map, style); + component = component.style(newStyle); + + Object extra = map.get("extra"); + if (extra != null) { + component = component.append(componentFromNbtTag(extra, newStyle)); + } + + return component; + } } - return translate; + + GeyserImpl.getInstance().getLogger().error("Expected tag to be a literal string, a list of components, or a component object with a text/translate key: " + nbtTag); + return Component.empty(); + } + + private static List componentsFromNbtList(List list, Style style) { + List components = new ArrayList<>(); + for (Object entry : list) { + components.add(componentFromNbtTag(entry, style)); + } + return components; + } + + public static Style getStyleFromNbtMap(NbtMap map) { + Style.Builder style = Style.style(); + + String colorString = map.getString("color", null); + if (colorString != null) { + if (colorString.startsWith(TextColor.HEX_PREFIX)) { + style.color(TextColor.fromHexString(colorString)); + } else { + style.color(NamedTextColor.NAMES.value(colorString)); + } + } + + map.listenForBoolean("bold", value -> style.decoration(TextDecoration.BOLD, value)); + map.listenForBoolean("italic", value -> style.decoration(TextDecoration.ITALIC, value)); + map.listenForBoolean("underlined", value -> style.decoration(TextDecoration.UNDERLINED, value)); + map.listenForBoolean("strikethrough", value -> style.decoration(TextDecoration.STRIKETHROUGH, value)); + map.listenForBoolean("obfuscated", value -> style.decoration(TextDecoration.OBFUSCATED, value)); + + return style.build(); + } + + public static Style getStyleFromNbtMap(NbtMap map, Style base) { + return base.merge(getStyleFromNbtMap(map)); } public static void init() { 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..8dc94a165 100644 --- a/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/DimensionUtils.java @@ -28,11 +28,9 @@ package org.geysermc.geyser.util; 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.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; @@ -89,18 +87,8 @@ public class DimensionUtils { 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); + session.updateRain(0); + session.updateThunder(0); finalizeDimensionSwitch(session, player); @@ -179,7 +167,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/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/InventoryUtils.java b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java index b0bfffc19..a0bd5a4c7 100644 --- a/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/InventoryUtils.java @@ -32,6 +32,8 @@ import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; +import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; +import org.cloudburstmc.protocol.bedrock.data.inventory.FullContainerName; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; import org.cloudburstmc.protocol.bedrock.packet.PlayerHotbarPacket; @@ -159,7 +161,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); @@ -180,6 +182,7 @@ public class InventoryUtils { cursorPacket.setContainerId(ContainerId.UI); cursorPacket.setSlot(0); cursorPacket.setItem(session.getPlayerInventory().getCursor().getItemData(session)); + cursorPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null)); session.sendUpstreamPacket(cursorPacket); } 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/bedrock/biome_definitions.dat b/core/src/main/resources/bedrock/biome_definitions.dat index dfee570e4..3ae94a5c8 100644 Binary files a/core/src/main/resources/bedrock/biome_definitions.dat and b/core/src/main/resources/bedrock/biome_definitions.dat differ 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 000000000..521ea3cc6 Binary files /dev/null and b/core/src/main/resources/bedrock/block_palette.1_21_20.nbt differ diff --git a/core/src/main/resources/bedrock/block_palette.1_21_30.nbt b/core/src/main/resources/bedrock/block_palette.1_21_30.nbt new file mode 100644 index 000000000..bb19c11ca Binary files /dev/null and b/core/src/main/resources/bedrock/block_palette.1_21_30.nbt differ diff --git a/core/src/main/resources/bedrock/creative_items.1_21_20.json b/core/src/main/resources/bedrock/creative_items.1_21_20.json new file mode 100644 index 000000000..ce008aa44 --- /dev/null +++ b/core/src/main/resources/bedrock/creative_items.1_21_20.json @@ -0,0 +1,6214 @@ +{ + "items": [ + { + "id": "minecraft:oak_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQFAAAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19wbGFua3MECQBuYW1lX2hhc2ilMDLR92rQ4wMKAG5ldHdvcmtfaWS2GotyCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:spruce_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAwAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9wbGFua3MECQBuYW1lX2hhc2iumBkmFGFE8gMKAG5ldHdvcmtfaWSo8TFgCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:birch_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX3BsYW5rcwQJAG5hbWVfaGFzaLrrAKJqV2WFAwoAbmV0d29ya19pZL+e3ZAKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:jungle_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAwAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9wbGFua3MECQBuYW1lX2hhc2iBM3k4T3FAugMKAG5ldHdvcmtfaWSXUmBCCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:acacia_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAwAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9wbGFua3MECQBuYW1lX2hhc2g60edJxO5/aAMKAG5ldHdvcmtfaWTUXozECgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:dark_oak_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTmAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX3BsYW5rcwQJAG5hbWVfaGFzaAr64wkQ9cA7AwoAbmV0d29ya19pZFbMeR0KBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:mangrove_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX3BsYW5rcwQJAG5hbWVfaGFzaPvLtcEA0F8xAwoAbmV0d29ya19pZEvnlCYKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:cherry_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9wbGFua3MECQBuYW1lX2hhc2hNIvVh/lVW7gMKAG5ldHdvcmtfaWQTXpRoCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:bamboo_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT9AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19wbGFua3MECQBuYW1lX2hhc2gYnjNz7SCCjgMKAG5ldHdvcmtfaWTi8ySSCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:bamboo_mosaic", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT8AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19tb3NhaWMECQBuYW1lX2hhc2izSEgiMKOp/AMKAG5ldHdvcmtfaWQZ/p8xCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:crimson_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTxAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fcGxhbmtzBAkAbmFtZV9oYXNoJc5IKqNXJnwDCgBuZXR3b3JrX2lkwtJDdQoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:warped_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTyAQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9wbGFua3MECQBuYW1lX2hhc2g3yGXEWhe6LgMKAG5ldHdvcmtfaWStTABvCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSE4JosCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCwBjb2JibGVzdG9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWTUvV6XCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEQBtb3NzeV9jb2JibGVzdG9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWT4opb2CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBwBncmFuaXRlCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQAMQTVCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBwBkaW9yaXRlCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQIbDOcCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCABhbmRlc2l0ZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSZKhusCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCQBzYW5kc3RvbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSp4zgCCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlDQByZWRfc2FuZHN0b25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRbqVHTCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCwBzdG9uZV9icmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRr0ZT/CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEQBtb3NzeV9zdG9uZV9icmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRnLis3CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlBQBicmljawgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQNLzfSCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlDABuZXRoZXJfYnJpY2sIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWQ5h0xwCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlEAByZWRfbmV0aGVyX2JyaWNrCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWS9J0B2CgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCQBlbmRfYnJpY2sIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWRPbkJeCgYAc3RhdGVzCA8Ad2FsbF9ibG9ja190eXBlCgBwcmlzbWFyaW5lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:blackstone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQUAgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsYWNrc3RvbmVfd2FsbAQJAG5hbWVfaGFzaMP8XppUSU1RAwoAbmV0d29ya19pZMbeBBsKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:polished_blackstone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQoAgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfd2FsbAQJAG5hbWVfaGFzaP6SwV08YwzAAwoAbmV0d29ya19pZAJLsz8KBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:polished_blackstone_brick_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQVAgAACAQAbmFtZSgAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfd2FsbAQJAG5hbWVfaGFzaBBIDZbHxiEzAwoAbmV0d29ya19pZEbLV8cKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:cobbled_deepslate_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR9AgAACAQAbmFtZSAAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3dhbGwECQBuYW1lX2hhc2iECY5oKxeT+gMKAG5ldHdvcmtfaWRCnPrFCgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:deepslate_tile_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3dhbGwECQBuYW1lX2hhc2jz7N+PeuEXgQMKAG5ldHdvcmtfaWTqw4s4CgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:polished_deepslate_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV93YWxsBAkAbmFtZV9oYXNoHxjTdj9pevMDCgBuZXR3b3JrX2lkIvBYYwoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:deepslate_brick_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSJAgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja193YWxsBAkAbmFtZV9oYXNoEs3EQrjroyEDCgBuZXR3b3JrX2lkwlrCGwoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:mud_brick_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAgAACAQAbmFtZRgAbWluZWNyYWZ0Om11ZF9icmlja193YWxsBAkAbmFtZV9oYXNov9b98ATpUSwDCgBuZXR3b3JrX2lkH/1WZQoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:oak_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRVAAAACAQAbmFtZRMAbWluZWNyYWZ0Om9ha19mZW5jZQQJAG5hbWVfaGFzaGEmid7AaCWRAwoAbmV0d29ya19pZDvPEXcKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:spruce_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRCAwAACAQAbmFtZRYAbWluZWNyYWZ0OnNwcnVjZV9mZW5jZQQJAG5hbWVfaGFzaPQCm+aX1ZQeAwoAbmV0d29ya19pZD1QUEoKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:birch_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ/AwAACAQAbmFtZRUAbWluZWNyYWZ0OmJpcmNoX2ZlbmNlBAkAbmFtZV9oYXNo6CJ2ATpANfgDCgBuZXR3b3JrX2lkmCUV2QoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:jungle_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRBAwAACAQAbmFtZRYAbWluZWNyYWZ0Omp1bmdsZV9mZW5jZQQJAG5hbWVfaGFzaOX4cD9uAmsdAwoAbmV0d29ya19pZHz1VxkKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:acacia_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ+AwAACAQAbmFtZRYAbWluZWNyYWZ0OmFjYWNpYV9mZW5jZQQJAG5hbWVfaGFzaGjn+RlKVDH6AwoAbmV0d29ya19pZNVGubwKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:dark_oak_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRAAwAACAQAbmFtZRgAbWluZWNyYWZ0OmRhcmtfb2FrX2ZlbmNlBAkAbmFtZV9oYXNoGPj0gCgM0c0DCgBuZXR3b3JrX2lk2w+gEwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:mangrove_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTqAgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hbmdyb3ZlX2ZlbmNlBAkAbmFtZV9oYXNowwAd7tPu9bsDCgBuZXR3b3JrX2lkKEcd0goGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:cherry_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAwAACAQAbmFtZRYAbWluZWNyYWZ0OmNoZXJyeV9mZW5jZQQJAG5hbWVfaGFzaFmtUfHfTxcxAwoAbmV0d29ya19pZPCBxAIKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:bamboo_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJhbWJvb19mZW5jZQQJAG5hbWVfaGFzaCKRbxfXsfkiAwoAbmV0d29ya19pZJNXKFcKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:nether_brick_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRxAAAACAQAbmFtZRwAbWluZWNyYWZ0Om5ldGhlcl9icmlja19mZW5jZQQJAG5hbWVfaGFzaA6030ngawxcAwoAbmV0d29ya19pZLnjLF4KBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:crimson_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT/AQAACAQAbmFtZRcAbWluZWNyYWZ0OmNyaW1zb25fZmVuY2UECQBuYW1lX2hhc2jhUhKv1HGj9AMKAG5ldHdvcmtfaWR3OH3OCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:warped_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQAAgAACAQAbmFtZRYAbWluZWNyYWZ0OndhcnBlZF9mZW5jZQQJAG5hbWVfaGFzaJfb3/YuKmOWAwoAbmV0d29ya19pZCpaGC8KBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRrAAAACAQAbmFtZRQAbWluZWNyYWZ0OmZlbmNlX2dhdGUECQBuYW1lX2hhc2hTxpjEDmRzAwMKAG5ldHdvcmtfaWR+T9kTCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:spruce_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS3AAAACAQAbmFtZRsAbWluZWNyYWZ0OnNwcnVjZV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoanTVB84HRbkDCgBuZXR3b3JrX2lkEnw5egoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:birch_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS4AAAACAQAbmFtZRoAbWluZWNyYWZ0OmJpcmNoX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2jmfPklI8azSwMKAG5ldHdvcmtfaWQL77/BCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:jungle_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS5AAAACAQAbmFtZRsAbWluZWNyYWZ0Omp1bmdsZV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNobYVQkfBomIcDCgBuZXR3b3JrX2lkA1zgtgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:acacia_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS7AAAACAQAbmFtZRsAbWluZWNyYWZ0OmFjYWNpYV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoZnrLUx/XSekDCgBuZXR3b3JrX2lkHg/kTgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:dark_oak_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS6AAAACAQAbmFtZR0AbWluZWNyYWZ0OmRhcmtfb2FrX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2j2PTvdJJHcVQMKAG5ldHdvcmtfaWTwjOCeCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:mangrove_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTrAgAACAQAbmFtZR0AbWluZWNyYWZ0Om1hbmdyb3ZlX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2i/kOhBKiI/dAMKAG5ldHdvcmtfaWSfweCSCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:cherry_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQUAwAACAQAbmFtZRsAbWluZWNyYWZ0OmNoZXJyeV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoKWLgCk0z+PsDCgBuZXR3b3JrX2lk/9bTZQoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:bamboo_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAwAACAQAbmFtZRsAbWluZWNyYWZ0OmJhbWJvb19mZW5jZV9nYXRlBAkAbmFtZV9oYXNopH1JrUgwdIADCgBuZXR3b3JrX2lkzIpPywoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:crimson_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAgAACAQAbmFtZRwAbWluZWNyYWZ0OmNyaW1zb25fZmVuY2VfZ2F0ZQQJAG5hbWVfaGFzaHE3Gfd0Z2d2AwoAbmV0d29ya19pZDQzVbEKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQsAaW5fd2FsbF9iaXQAAQgAb3Blbl9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:warped_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAgAACAQAbmFtZRsAbWluZWNyYWZ0OndhcnBlZF9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoy0oIBjDIG4kDCgBuZXR3b3JrX2lkkf+/3QoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:normal_stone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAQAACAQAbmFtZR0AbWluZWNyYWZ0Om5vcm1hbF9zdG9uZV9zdGFpcnMECQBuYW1lX2hhc2hAEktZZOkGIwMKAG5ldHdvcmtfaWQeH1ALCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:stone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRDAAAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX3N0YWlycwQJAG5hbWVfaGFzaNRjqVC5GRVDAwoAbmV0d29ya19pZDcCv+MKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:mossy_cobblestone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSyAQAACAQAbmFtZSIAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lX3N0YWlycwQJAG5hbWVfaGFzaMVSTq5z9n1RAwoAbmV0d29ya19pZFIfrhkKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:oak_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ1AAAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19zdGFpcnMECQBuYW1lX2hhc2jk/HFzdXy0FQMKAG5ldHdvcmtfaWQJjyzBCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:spruce_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSGAAAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9zdGFpcnMECQBuYW1lX2hhc2iznygw7uBPBQMKAG5ldHdvcmtfaWTv+is3CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:birch_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSHAAAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX3N0YWlycwQJAG5hbWVfaGFzaPfhbL619a3GAwoAbmV0d29ya19pZFyPlHAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:jungle_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSIAAAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9zdGFpcnMECQBuYW1lX2hhc2jodJsHUbOVxQMKAG5ldHdvcmtfaWR0z5d4CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:acacia_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSjAAAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9zdGFpcnMECQBuYW1lX2hhc2h3x1NmD43IqQMKAG5ldHdvcmtfaWS7Jwz6CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:dark_oak_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAAAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX3N0YWlycwQJAG5hbWVfaGFzaMfwkbYPbNmAAwoAbmV0d29ya19pZCmBYKAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:mangrove_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTnAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX3N0YWlycwQJAG5hbWVfaGFzaNpUDY+uGMpyAwoAbmV0d29ya19pZChzUAsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:cherry_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQcAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9zdGFpcnMECQBuYW1lX2hhc2jMtr0v9JY4zwMKAG5ldHdvcmtfaWRQwq31CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:bamboo_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT/AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19zdGFpcnMECQBuYW1lX2hhc2jFOzWL8PalKwMKAG5ldHdvcmtfaWTVPh42CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:bamboo_mosaic_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQKAwAACAQAbmFtZR4AbWluZWNyYWZ0OmJhbWJvb19tb3NhaWNfc3RhaXJzBAkAbmFtZV9oYXNoNLPiveSHPaoDCgBuZXR3b3JrX2lk44PHjgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:stone_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRtAAAACAQAbmFtZRwAbWluZWNyYWZ0OnN0b25lX2JyaWNrX3N0YWlycwQJAG5hbWVfaGFzaN6tQViRo5cwAwoAbmV0d29ya19pZDMyMgIKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:mossy_stone_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSuAQAACAQAbmFtZSIAbWluZWNyYWZ0Om1vc3N5X3N0b25lX2JyaWNrX3N0YWlycwQJAG5hbWVfaGFzaIB/Zv5YBPuYAwoAbmV0d29ya19pZANTOsMKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:sandstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSAAAAACAQAbmFtZRoAbWluZWNyYWZ0OnNhbmRzdG9uZV9zdGFpcnMECQBuYW1lX2hhc2hOyA0BoYUOPQMKAG5ldHdvcmtfaWSV/834CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:smooth_sandstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSwAQAACAQAbmFtZSEAbWluZWNyYWZ0OnNtb290aF9zYW5kc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNoB+CuCd8Ruz8DCgBuZXR3b3JrX2lksR+m8QoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:red_sandstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS0AAAACAQAbmFtZR4AbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNoPs0LpHPL24YDCgBuZXR3b3JrX2lkLYVt3woGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:smooth_red_sandstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAQAACAQAbmFtZSUAbWluZWNyYWZ0OnNtb290aF9yZWRfc2FuZHN0b25lX3N0YWlycwQJAG5hbWVfaGFzaBvjtQv5pf+MAwoAbmV0d29ya19pZMHNND8KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:granite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAQAACAQAbmFtZRgAbWluZWNyYWZ0OmdyYW5pdGVfc3RhaXJzBAkAbmFtZV9oYXNoGzpvtoqKQjgDCgBuZXR3b3JrX2lkPkcB1goGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:polished_granite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAQAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2dyYW5pdGVfc3RhaXJzBAkAbmFtZV9oYXNo3PvbSfEQklIDCgBuZXR3b3JrX2lkMmEm3AoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:diorite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAQAACAQAbmFtZRgAbWluZWNyYWZ0OmRpb3JpdGVfc3RhaXJzBAkAbmFtZV9oYXNoi73T8VQuZmcDCgBuZXR3b3JrX2lk6i6nBQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:polished_diorite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSsAQAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2Rpb3JpdGVfc3RhaXJzBAkAbmFtZV9oYXNoFKRJd5Wk5L0DCgBuZXR3b3JrX2lkbt2ioAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:andesite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAQAACAQAbmFtZRkAbWluZWNyYWZ0OmFuZGVzaXRlX3N0YWlycwQJAG5hbWVfaGFzaO5w2FKBw76EAwoAbmV0d29ya19pZKhXEgUKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:polished_andesite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWStAQAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2FuZGVzaXRlX3N0YWlycwQJAG5hbWVfaGFzaNcZZ/zmLInIAwoAbmV0d29ya19pZJTHrlEKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRsAAAACAQAbmFtZRYAbWluZWNyYWZ0OmJyaWNrX3N0YWlycwQJAG5hbWVfaGFzaMyt+cRDk5O2AwoAbmV0d29ya19pZNeMh58KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:nether_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRyAAAACAQAbmFtZR0AbWluZWNyYWZ0Om5ldGhlcl9icmlja19zdGFpcnMECQBuYW1lX2hhc2jRqIoOXgifBAMKAG5ldHdvcmtfaWQDiw5yCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:red_nether_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS3AQAACAQAbmFtZSEAbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNogQvosSbcj7kDCgBuZXR3b3JrX2lkx2IMtAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:end_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSxAQAACAQAbmFtZRoAbWluZWNyYWZ0OmVuZF9icmlja19zdGFpcnMECQBuYW1lX2hhc2hmlAk+QhsUsQMKAG5ldHdvcmtfaWTN7KFaCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:quartz_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWScAAAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9zdGFpcnMECQBuYW1lX2hhc2hmvpvOqGi6egMKAG5ldHdvcmtfaWRmUTh7CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:smooth_quartz_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS4AQAACAQAbmFtZR4AbWluZWNyYWZ0OnNtb290aF9xdWFydHpfc3RhaXJzBAkAbmFtZV9oYXNoNZZ9rX0qZOsDCgBuZXR3b3JrX2lkzsgQyQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:purpur_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAAAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnB1cl9zdGFpcnMECQBuYW1lX2hhc2ifwDxeezXD7gMKAG5ldHdvcmtfaWTT+rxiCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:prismarine_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAQAACAQAbmFtZRsAbWluZWNyYWZ0OnByaXNtYXJpbmVfc3RhaXJzBAkAbmFtZV9oYXNooTHSZ+IrYtcDCgBuZXR3b3JrX2lkxTJfeAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:dark_prismarine_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAQAACAQAbmFtZSAAbWluZWNyYWZ0OmRhcmtfcHJpc21hcmluZV9zdGFpcnMECQBuYW1lX2hhc2hIciLmam4o4AMKAG5ldHdvcmtfaWTVu7TCCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:prismarine_bricks_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAQAACAQAbmFtZSIAbWluZWNyYWZ0OnByaXNtYXJpbmVfYnJpY2tzX3N0YWlycwQJAG5hbWVfaGFzaNIjq1oBlZMMAwoAbmV0d29ya19pZGEFwLYKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:crimson_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT9AQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fc3RhaXJzBAkAbmFtZV9oYXNoZJqIzCBpCq4DCgBuZXR3b3JrX2lktXE00AoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:warped_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT+AQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9zdGFpcnMECQBuYW1lX2hhc2hOkY27jLD4RQMKAG5ldHdvcmtfaWQ+E5VrCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:blackstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAgAACAQAbmFtZRsAbWluZWNyYWZ0OmJsYWNrc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNokdoUb76p9McDCgBuZXR3b3JrX2lk5fWI5goGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:polished_blackstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQjAgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNolCFtFIE8MmADCgBuZXR3b3JrX2lkGTf7sgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:polished_blackstone_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQSAgAACAQAbmFtZSoAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNonks6UlfpOmkDCgBuZXR3b3JrX2lkgYeOdAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAgAACAQAbmFtZRsAbWluZWNyYWZ0OmN1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoHfoAXYq5G3MDCgBuZXR3b3JrX2lkeetf7woGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:exposed_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAgAACAQAbmFtZSMAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcl9zdGFpcnMECQBuYW1lX2hhc2howneQGtZ9cgMKAG5ldHdvcmtfaWSg73zdCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:weathered_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAgAACAQAbmFtZSUAbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyX3N0YWlycwQJAG5hbWVfaGFzaP+R5loXxrVgAwoAbmV0d29ya19pZOnbRf4KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:oxidized_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRkAgAACAQAbmFtZSQAbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNo6Jeoq5rsPxsDCgBuZXR3b3JrX2lkmRjDnQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:waxed_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRlAgAACAQAbmFtZSEAbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoh07CQj0/SR8DCgBuZXR3b3JrX2lkmYqoqAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:waxed_exposed_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRmAgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcl9zdGFpcnMECQBuYW1lX2hhc2guVct1ilmxTwMKAG5ldHdvcmtfaWQgCPROCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:waxed_weathered_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRnAgAACAQAbmFtZSsAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyX3N0YWlycwQJAG5hbWVfaGFzaPXC8Sz/phCpAwoAbmV0d29ya19pZHlwHVsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:waxed_oxidized_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS/AgAACAQAbmFtZSoAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoaqGdkuhxVZUDCgBuZXR3b3JrX2lkYQXzzgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:cobbled_deepslate_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR8AgAACAQAbmFtZSIAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3N0YWlycwQJAG5hbWVfaGFzaPIfa+TpyJcIAwoAbmV0d29ya19pZJUvOYIKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:deepslate_tile_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3N0YWlycwQJAG5hbWVfaGFzaGFRFzB72mN2AwoAbmV0d29ya19pZJEOgIsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:polished_deepslate_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSAAgAACAQAbmFtZSMAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV9zdGFpcnMECQBuYW1lX2hhc2iNCYxVik9sGAMKAG5ldHdvcmtfaWSRVPnYCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:deepslate_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSIAgAACAQAbmFtZSAAbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja19zdGFpcnMECQBuYW1lX2hhc2hIasOahEf83wMKAG5ldHdvcmtfaWQ1qEDCCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:mud_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAgAACAQAbmFtZRoAbWluZWNyYWZ0Om11ZF9icmlja19zdGFpcnMECQBuYW1lX2hhc2gt3qxK1NWajAMKAG5ldHdvcmtfaWSm9N3MCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "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": "CgAAAwgAYmxvY2tfaWRgAAAACAQAbmFtZRIAbWluZWNyYWZ0OnRyYXBkb29yBAkAbmFtZV9oYXNotYiAJGtN0xADCgBuZXR3b3JrX2lkyTAWkAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:spruce_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSUAQAACAQAbmFtZRkAbWluZWNyYWZ0OnNwcnVjZV90cmFwZG9vcgQJAG5hbWVfaGFzaOwlfbgBkUW4AwoAbmV0d29ya19pZPHy1K0KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:birch_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAQAACAQAbmFtZRgAbWluZWNyYWZ0OmJpcmNoX3RyYXBkb29yBAkAbmFtZV9oYXNoSLtLweOLJ7wDCgBuZXR3b3JrX2lkeJWDfgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:jungle_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSTAQAACAQAbmFtZRkAbWluZWNyYWZ0Omp1bmdsZV90cmFwZG9vcgQJAG5hbWVfaGFzaDP/TnM9wyCIAwoAbmV0d29ya19pZEy2fJoKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:acacia_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSQAQAACAQAbmFtZRkAbWluZWNyYWZ0OmFjYWNpYV90cmFwZG9vcgQJAG5hbWVfaGFzaMj8xi3vmEKOAwoAbmV0d29ya19pZOHj8E8KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:dark_oak_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSSAQAACAQAbmFtZRsAbWluZWNyYWZ0OmRhcmtfb2FrX3RyYXBkb29yBAkAbmFtZV9oYXNomB2GGJQ2aOMDCgBuZXR3b3JrX2lko5ZHTwoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:mangrove_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTvAgAACAQAbmFtZRsAbWluZWNyYWZ0Om1hbmdyb3ZlX3RyYXBkb29yBAkAbmFtZV9oYXNooV3kQsQUUmkDCgBuZXR3b3JrX2lkkF/mxAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:cherry_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQeAwAACAQAbmFtZRkAbWluZWNyYWZ0OmNoZXJyeV90cmFwZG9vcgQJAG5hbWVfaGFzaH/PefpfdHgtAwoAbmV0d29ya19pZOA7eNgKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:bamboo_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAwAACAQAbmFtZRkAbWluZWNyYWZ0OmJhbWJvb190cmFwZG9vcgQJAG5hbWVfaGFzaJrEOpsTwtKCAwoAbmV0d29ya19pZLvbPz8KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:iron_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSnAAAACAQAbmFtZRcAbWluZWNyYWZ0Omlyb25fdHJhcGRvb3IECQBuYW1lX2hhc2gwA+IumsEiGQMKAG5ldHdvcmtfaWTvSVl/CgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:crimson_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT1AQAACAQAbmFtZRoAbWluZWNyYWZ0OmNyaW1zb25fdHJhcGRvb3IECQBuYW1lX2hhc2jHXufTnwUkYgMKAG5ldHdvcmtfaWQLjMYVCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:warped_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT2AQAACAQAbmFtZRkAbWluZWNyYWZ0OndhcnBlZF90cmFwZG9vcgQJAG5hbWVfaGFzaA20wG/+vkd6AwoAbmV0d29ya19pZHKR/hYKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:iron_bars", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRlAAAACAQAbmFtZRMAbWluZWNyYWZ0Omlyb25fYmFycwQJAG5hbWVfaGFzaPuefWSNAe56AwoAbmV0d29ya19pZN2LB5IKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQUAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmdsYXNzBAkAbmFtZV9oYXNowGJByfWff6gDCgBuZXR3b3JrX2lk0hdLNwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:white_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTxAAAACAQAbmFtZR0AbWluZWNyYWZ0OndoaXRlX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2iHubqoMbu9fAMKAG5ldHdvcmtfaWRndBrUCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:light_gray_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSnAwAACAQAbmFtZSIAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaKKa+LrRsHQhAwoAbmV0d29ya19pZEv2giYKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:gray_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSmAwAACAQAbmFtZRwAbWluZWNyYWZ0OmdyYXlfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaIETy7Y/HZREAwoAbmV0d29ya19pZDomVrUKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:black_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSuAwAACAQAbmFtZR0AbWluZWNyYWZ0OmJsYWNrX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2iV6BCwpfDMmwMKAG5ldHdvcmtfaWSV7doJCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:brown_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAwAACAQAbmFtZR0AbWluZWNyYWZ0OmJyb3duX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2igsEiq5np8JgMKAG5ldHdvcmtfaWRMzE/lCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:red_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWStAwAACAQAbmFtZRsAbWluZWNyYWZ0OnJlZF9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNoCa2J12/lQoIDCgBuZXR3b3JrX2lk283lWAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:orange_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSgAwAACAQAbmFtZR4AbWluZWNyYWZ0Om9yYW5nZV9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNozgjAuvzhxGsDCgBuZXR3b3JrX2lkW5CkhQoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:yellow_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSjAwAACAQAbmFtZR4AbWluZWNyYWZ0OnllbGxvd19zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNo7EbHMd5WVugDCgBuZXR3b3JrX2lkkdDyXQoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:lime_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAwAACAQAbmFtZRwAbWluZWNyYWZ0OmxpbWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaBtZA1nZtwcFAwoAbmV0d29ya19pZDxX85UKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:green_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSsAwAACAQAbmFtZR0AbWluZWNyYWZ0OmdyZWVuX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2h91ptDgbehWwMKAG5ldHdvcmtfaWTlDhnECgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:cyan_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAwAACAQAbmFtZRwAbWluZWNyYWZ0OmN5YW5fc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaBkIYQ8nQLqbAwoAbmV0d29ya19pZOL1lHsKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:light_blue_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAwAACAQAbmFtZSIAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaLt05n1G0fiSAwoAbmV0d29ya19pZNbwulIKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:blue_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAwAACAQAbmFtZRwAbWluZWNyYWZ0OmJsdWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaPhLocSfzduRAwoAbmV0d29ya19pZENsjFwKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:purple_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAwAACAQAbmFtZR4AbWluZWNyYWZ0OnB1cnBsZV9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNoJk0DhRO0szUDCgBuZXR3b3JrX2lkD98ZxgoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:magenta_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAwAACAQAbmFtZR8AbWluZWNyYWZ0Om1hZ2VudGFfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaFEDeFiJj3zSAwoAbmV0d29ya19pZG+iFRoKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:pink_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAwAACAQAbmFtZRwAbWluZWNyYWZ0OnBpbmtfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaDijTX87ywxhAwoAbmV0d29ya19pZKdEricKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:tinted_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRNAgAACAQAbmFtZRYAbWluZWNyYWZ0OnRpbnRlZF9nbGFzcwQJAG5hbWVfaGFzaAFZWSamk6KdAwoAbmV0d29ya19pZGSvWX8KBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRmAAAACAQAbmFtZRQAbWluZWNyYWZ0OmdsYXNzX3BhbmUECQBuYW1lX2hhc2gRSBHwNMQ4gQMKAG5ldHdvcmtfaWRGwixuCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:white_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSgAAAACAQAbmFtZSIAbWluZWNyYWZ0OndoaXRlX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaHgxQmgJVtRrAwoAbmV0d29ya19pZBEr/DYKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:light_gray_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSJAwAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNon0aQw9lNkSEDCgBuZXR3b3JrX2lk9dp5VgoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:gray_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSIAwAACAQAbmFtZSEAbWluZWNyYWZ0OmdyYXlfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNors74IIw+2MMDCgBuZXR3b3JrX2lkmrGO5woGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:black_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSQAwAACAQAbmFtZSIAbWluZWNyYWZ0OmJsYWNrX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaOK/5ZRRd+M1AwoAbmV0d29ya19pZDv++oQKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:brown_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSNAwAACAQAbmFtZSIAbWluZWNyYWZ0OmJyb3duX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLHeGJyRFTIWAwoAbmV0d29ya19pZMz9L0wKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:red_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAwAACAQAbmFtZSAAbWluZWNyYWZ0OnJlZF9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2gGr4x6JheAywMKAG5ldHdvcmtfaWQBjCTmCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:orange_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAwAACAQAbmFtZSMAbWluZWNyYWZ0Om9yYW5nZV9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2hbHxPD2gEbEAMKAG5ldHdvcmtfaWSt/7a5CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:yellow_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAwAACAQAbmFtZSMAbWluZWNyYWZ0OnllbGxvd19zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2g9tl4aOCyZBwMKAG5ldHdvcmtfaWTXRAS7CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:lime_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSGAwAACAQAbmFtZSEAbWluZWNyYWZ0OmxpbWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNo3CtUyLwoGegDCgBuZXR3b3JrX2lkYJDnggoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:green_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSOAwAACAQAbmFtZSIAbWluZWNyYWZ0OmdyZWVuX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaJo6YP7IMy9SAwoAbmV0d29ya19pZHOnixoKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:cyan_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAwAACAQAbmFtZSEAbWluZWNyYWZ0OmN5YW5fc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoti97c6QrbLQDCgBuZXR3b3JrX2lkUqFUeQoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:light_blue_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAwAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNovDg/gQle104DCgBuZXR3b3JrX2lkFuy4MQoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:blue_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSMAwAACAQAbmFtZSEAbWluZWNyYWZ0OmJsdWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoGc57tiexbQMDCgBuZXR3b3JrX2lk1eBLUAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:purple_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAwAACAQAbmFtZSMAbWluZWNyYWZ0OnB1cnBsZV9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2hDJHYdd0FdfQMKAG5ldHdvcmtfaWSNsdK5CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:magenta_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAwAACAQAbmFtZSQAbWluZWNyYWZ0Om1hZ2VudGFfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNo3pcOw5bs5XoDCgBuZXR3b3JrX2lkVbOR7AoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:pink_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSHAwAACAQAbmFtZSEAbWluZWNyYWZ0OnBpbmtfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoWRhSACMWgswDCgBuZXR3b3JrX2lkIR92xwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:ladder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRBAAAACAQAbmFtZRAAbWluZWNyYWZ0OmxhZGRlcgQJAG5hbWVfaGFzaKBhqheJVOz+AwoAbmV0d29ya19pZCgvzlsKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:scaffolding", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAQAACAQAbmFtZRUAbWluZWNyYWZ0OnNjYWZmb2xkaW5nBAkAbmFtZV9oYXNoYrkevrqcljwDCgBuZXR3b3JrX2lkD13mlAoGAHN0YXRlcwMJAHN0YWJpbGl0eQAAAAABDwBzdGFiaWxpdHlfY2hlY2sAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:smooth_stone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRsAbWluZWNyYWZ0OnNtb290aF9zdG9uZV9zbGFiBAkAbmFtZV9oYXNon5I1yVw74uMDCgBuZXR3b3JrX2lkqvjcBQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:normal_stone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCBAAACAQAbmFtZRsAbWluZWNyYWZ0Om5vcm1hbF9zdG9uZV9zbGFiBAkAbmFtZV9oYXNoIvsjJLQdolcDCgBuZXR3b3JrX2lkC1zqRQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:cobblestone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRoBAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3NsYWIECQBuYW1lX2hhc2h5CXtW7vlQVgMKAG5ldHdvcmtfaWRDGyj2CgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:mossy_cobblestone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR3BAAACAQAbmFtZSAAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lX3NsYWIECQBuYW1lX2hhc2ijm1BCwB82VgMKAG5ldHdvcmtfaWR7ByMGCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:oak_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAAAACAQAbmFtZRIAbWluZWNyYWZ0Om9ha19zbGFiBAkAbmFtZV9oYXNoJp1Cp1M4jlwDCgBuZXR3b3JrX2lkZH6+owoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:spruce_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQjBAAACAQAbmFtZRUAbWluZWNyYWZ0OnNwcnVjZV9zbGFiBAkAbmFtZV9oYXNodQi70jB238cDCgBuZXR3b3JrX2lkrriOYQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:birch_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQkBAAACAQAbmFtZRQAbWluZWNyYWZ0OmJpcmNoX3NsYWIECQBuYW1lX2hhc2gZPpfMxoOsTAMKAG5ldHdvcmtfaWThR9jyCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:jungle_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQlBAAACAQAbmFtZRUAbWluZWNyYWZ0Omp1bmdsZV9zbGFiBAkAbmFtZV9oYXNo6gLs79NXak4DCgBuZXR3b3JrX2lk5ZiKgwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:acacia_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmBAAACAQAbmFtZRUAbWluZWNyYWZ0OmFjYWNpYV9zbGFiBAkAbmFtZV9oYXNomSdFmDnv4OUDCgBuZXR3b3JrX2lkHttaXAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:dark_oak_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQnBAAACAQAbmFtZRcAbWluZWNyYWZ0OmRhcmtfb2FrX3NsYWIECQBuYW1lX2hhc2hJjTohRFyhIQMKAG5ldHdvcmtfaWRMzDTyCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:mangrove_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWToAgAACAQAbmFtZRcAbWluZWNyYWZ0Om1hbmdyb3ZlX3NsYWIECQBuYW1lX2hhc2jYCcmhJPeNMwMKAG5ldHdvcmtfaWQx6U1yCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:cherry_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQaAwAACAQAbmFtZRUAbWluZWNyYWZ0OmNoZXJyeV9zbGFiBAkAbmFtZV9oYXNoTt0MmVn/mqoDCgBuZXR3b3JrX2lk2VVsZQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:bamboo_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQAAwAACAQAbmFtZRUAbWluZWNyYWZ0OmJhbWJvb19zbGFiBAkAbmFtZV9oYXNoo1xuFqINeLYDCgBuZXR3b3JrX2lkVC+0twoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:bamboo_mosaic_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQLAwAACAQAbmFtZRwAbWluZWNyYWZ0OmJhbWJvb19tb3NhaWNfc2xhYgQJAG5hbWVfaGFzaNbVRBZ/ChI3AwoAbmV0d29ya19pZOLZHFMKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:stone_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRqBAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2JyaWNrX3NsYWIECQBuYW1lX2hhc2js6EexuKuzrQMKAG5ldHdvcmtfaWRSsMxaCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:mossy_stone_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZSAAbWluZWNyYWZ0Om1vc3N5X3N0b25lX2JyaWNrX3NsYWIECQBuYW1lX2hhc2hiA4kFUl4tHAMKAG5ldHdvcmtfaWS6joSOCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:sandstone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRnBAAACAQAbmFtZRgAbWluZWNyYWZ0OnNhbmRzdG9uZV9zbGFiBAkAbmFtZV9oYXNo/GMI0MZnrhsDCgBuZXR3b3JrX2lkFP8WmwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:cut_sandstone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDBAAACAQAbmFtZRwAbWluZWNyYWZ0OmN1dF9zYW5kc3RvbmVfc2xhYgQJAG5hbWVfaGFzaE+zxVQweViJAwoAbmV0d29ya19pZHsu74YKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:smooth_sandstone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR4BAAACAQAbmFtZR8AbWluZWNyYWZ0OnNtb290aF9zYW5kc3RvbmVfc2xhYgQJAG5hbWVfaGFzaIkmsO1gw3gnAwoAbmV0d29ya19pZFSiwP0KBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:red_sandstone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRwAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmVfc2xhYgQJAG5hbWVfaGFzaEyDjeWlUHItAwoAbmV0d29ya19pZIT4rmwKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:cut_red_sandstone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEBAAACAQAbmFtZSAAbWluZWNyYWZ0OmN1dF9yZWRfc2FuZHN0b25lX3NsYWIECQBuYW1lX2hhc2hTVRS++snU3wMKAG5ldHdvcmtfaWSvIAviCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:smooth_red_sandstone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR6BAAACAQAbmFtZSMAbWluZWNyYWZ0OnNtb290aF9yZWRfc2FuZHN0b25lX3NsYWIECQBuYW1lX2hhc2i9iN2UK272tgMKAG5ldHdvcmtfaWRUZrwJCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:granite_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR/BAAACAQAbmFtZRYAbWluZWNyYWZ0OmdyYW5pdGVfc2xhYgQJAG5hbWVfaGFzaL0HprlAhhZwAwoAbmV0d29ya19pZIcIdc8KBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:polished_granite_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSABAAACAQAbmFtZR8AbWluZWNyYWZ0OnBvbGlzaGVkX2dyYW5pdGVfc2xhYgQJAG5hbWVfaGFzaP6bXk5w2dGrAwoAbmV0d29ya19pZCsRy1cKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:diorite_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR9BAAACAQAbmFtZRYAbWluZWNyYWZ0OmRpb3JpdGVfc2xhYgQJAG5hbWVfaGFzaM3ppS8v55sNAwoAbmV0d29ya19pZB+Pv9oKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:polished_diorite_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR+BAAACAQAbmFtZR8AbWluZWNyYWZ0OnBvbGlzaGVkX2Rpb3JpdGVfc2xhYgQJAG5hbWVfaGFzaLZlyJLkMPhyAwoAbmV0d29ya19pZFM0HYwKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:andesite_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR8BAAACAQAbmFtZRcAbWluZWNyYWZ0OmFuZGVzaXRlX3NsYWIECQBuYW1lX2hhc2icIrtuy/aosAMKAG5ldHdvcmtfaWTtXTtYCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:polished_andesite_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR7BAAACAQAbmFtZSAAbWluZWNyYWZ0OnBvbGlzaGVkX2FuZGVzaXRlX3NsYWIECQBuYW1lX2hhc2j56zJOfCF+3wMKAG5ldHdvcmtfaWRBs69FCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRpBAAACAQAbmFtZRQAbWluZWNyYWZ0OmJyaWNrX3NsYWIECQBuYW1lX2hhc2hO/Da4jU2v4wMKAG5ldHdvcmtfaWRG/qphCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:nether_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRsBAAACAQAbmFtZRsAbWluZWNyYWZ0Om5ldGhlcl9icmlja19zbGFiBAkAbmFtZV9oYXNonymoa2zbbqMDCgBuZXR3b3JrX2lkquvR1QoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:red_nether_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR5BAAACAQAbmFtZR8AbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2tfc2xhYgQJAG5hbWVfaGFzaG89ujUk3Y64AwoAbmV0d29ya19pZEZIunAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:end_stone_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZR4AbWluZWNyYWZ0OmVuZF9zdG9uZV9icmlja19zbGFiBAkAbmFtZV9oYXNo4tkxQtl+IyQDCgBuZXR3b3JrX2lkhByH/woGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:quartz_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRrBAAACAQAbmFtZRUAbWluZWNyYWZ0OnF1YXJ0el9zbGFiBAkAbmFtZV9oYXNo9JMj3upfsbwDCgBuZXR3b3JrX2lkn2g2VAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:smooth_quartz_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBBAAACAQAbmFtZRwAbWluZWNyYWZ0OnNtb290aF9xdWFydHpfc2xhYgQJAG5hbWVfaGFzaHOSJv8ve0nmAwoAbmV0d29ya19pZFMk/JsKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:purpur_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRzBAAACAQAbmFtZRUAbWluZWNyYWZ0OnB1cnB1cl9zbGFiBAkAbmFtZV9oYXNo4XeWbKpx2ScDCgBuZXR3b3JrX2lkRkga5goGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:prismarine_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR0BAAACAQAbmFtZRkAbWluZWNyYWZ0OnByaXNtYXJpbmVfc2xhYgQJAG5hbWVfaGFzaI9x+1fY8QRfAwoAbmV0d29ya19pZBTUZhwKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:dark_prismarine_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR1BAAACAQAbmFtZR4AbWluZWNyYWZ0OmRhcmtfcHJpc21hcmluZV9zbGFiBAkAbmFtZV9oYXNoSsZGDkEL5ZUDCgBuZXR3b3JrX2lkNLQ8VwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:prismarine_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR2BAAACAQAbmFtZR8AbWluZWNyYWZ0OnByaXNtYXJpbmVfYnJpY2tfc2xhYgQJAG5hbWVfaGFzaB1FSbVi97xJAwoAbmV0d29ya19pZEBwwFMKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:crimson_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAgAACAQAbmFtZRYAbWluZWNyYWZ0OmNyaW1zb25fc2xhYgQJAG5hbWVfaGFzaKZ+EfP0ZYOZAwoAbmV0d29ya19pZAxRUWAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:warped_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQIAgAACAQAbmFtZRUAbWluZWNyYWZ0OndhcnBlZF9zbGFiBAkAbmFtZV9oYXNo/AT0e/Z9W7UDCgBuZXR3b3JrX2lk1yq11AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:blackstone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQZAgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsYWNrc3RvbmVfc2xhYgQJAG5hbWVfaGFzaF/DD4ZUlNgtAwoAbmV0d29ya19pZGy1DjwKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:polished_blackstone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQkAgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfc2xhYgQJAG5hbWVfaGFzaDYnuUs86EWfAwoAbmV0d29ya19pZJj2bXIKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:polished_blackstone_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQbAgAACAQAbmFtZSgAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfc2xhYgQJAG5hbWVfaGFzaKySLqvHc4xXAwoAbmV0d29ya19pZOyWX94KBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRoAgAACAQAbmFtZRkAbWluZWNyYWZ0OmN1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaDsNpb2qs4iBAwoAbmV0d29ya19pZOTm2nsKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:exposed_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRpAgAACAQAbmFtZSEAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcl9zbGFiBAkAbmFtZV9oYXNoahQ5OwIQb7kDCgBuZXR3b3JrX2lkrUlZLwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:weathered_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRqAgAACAQAbmFtZSMAbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyX3NsYWIECQBuYW1lX2hhc2hBIuGIOVVXogMKAG5ldHdvcmtfaWQgnaDiCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:oxidized_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRrAgAACAQAbmFtZSIAbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaOptj9ycfpaDAwoAbmV0d29ya19pZMzFSRgKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:waxed_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRsAgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaAlx6DZOCTHzAwoAbmV0d29ya19pZFRBvDAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:waxed_exposed_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRtAgAACAQAbmFtZScAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcl9zbGFiBAkAbmFtZV9oYXNo3KqS5OnhtRIDCgBuZXR3b3JrX2lkHTGcTgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:waxed_weathered_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRuAgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyX3NsYWIECQBuYW1lX2hhc2gzZ1oX0HCFtwMKAG5ldHdvcmtfaWSgJR+XCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:waxed_oxidized_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTAAgAACAQAbmFtZSgAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaMjjTnLu1KcqAwoAbmV0d29ya19pZIxsnFYKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:cobbled_deepslate_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR7AgAACAQAbmFtZSAAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3NsYWIECQBuYW1lX2hhc2gwJIVWK1TM2QMKAG5ldHdvcmtfaWTYAoX5CgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:polished_deepslate_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR/AgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV9zbGFiBAkAbmFtZV9oYXNoC/Adiz8k6RYDCgBuZXR3b3JrX2lkuFYMAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:deepslate_tile_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3NsYWIECQBuYW1lX2hhc2hPydV6emzIXAMKAG5ldHdvcmtfaWQwlbFCCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:deepslate_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSHAgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja19zbGFiBAkAbmFtZV9oYXNoSv62V7iw10UDCgBuZXR3b3JrX2lkWMoragoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:mud_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAgAACAQAbmFtZRgAbWluZWNyYWZ0Om11ZF9icmlja19zbGFiBAkAbmFtZV9oYXNoq/tGBQWkv08DCgBuZXR3b3JrX2lkl4nnMwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:brick_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQtAAAACAQAbmFtZRUAbWluZWNyYWZ0OmJyaWNrX2Jsb2NrBAkAbmFtZV9oYXNo5Qc2E005S3oDCgBuZXR3b3JrX2lkqeGWRgoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:chiseled_nether_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQtAgAACAQAbmFtZSAAbWluZWNyYWZ0OmNoaXNlbGVkX25ldGhlcl9icmlja3MECQBuYW1lX2hhc2g31SBPTcUK1QMKAG5ldHdvcmtfaWS8TJ+TCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:cracked_nether_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQuAgAACAQAbmFtZR8AbWluZWNyYWZ0OmNyYWNrZWRfbmV0aGVyX2JyaWNrcwQJAG5hbWVfaGFzaAdC6eKzXT5tAwoAbmV0d29ya19pZIUSejwKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:quartz_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQvAgAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9icmlja3MECQBuYW1lX2hhc2jSZO590dd8sAMKAG5ldHdvcmtfaWSc5xCLCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:stone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAAAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX2JyaWNrcwQJAG5hbWVfaGFzaGAiQu8VWVJRAwoAbmV0d29ya19pZH2DjXUKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:mossy_stone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjBAAACAQAbmFtZRwAbWluZWNyYWZ0Om1vc3N5X3N0b25lX2JyaWNrcwQJAG5hbWVfaGFzaIZBO00MONRIAwoAbmV0d29ya19pZL2WDrAKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:cracked_stone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRkBAAACAQAbmFtZR4AbWluZWNyYWZ0OmNyYWNrZWRfc3RvbmVfYnJpY2tzBAkAbmFtZV9oYXNocIkAp6riMz4DCgBuZXR3b3JrX2lkTWGeCwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:chiseled_stone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRlBAAACAQAbmFtZR8AbWluZWNyYWZ0OmNoaXNlbGVkX3N0b25lX2JyaWNrcwQJAG5hbWVfaGFzaMB2FPLLADkEAwoAbmV0d29ya19pZOIPn0IKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:end_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTOAAAACAQAbmFtZRQAbWluZWNyYWZ0OmVuZF9icmlja3MECQBuYW1lX2hhc2hIUFfxNLZaFgMKAG5ldHdvcmtfaWQ/vDihCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:prismarine_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzBAAACAQAbmFtZRsAbWluZWNyYWZ0OnByaXNtYXJpbmVfYnJpY2tzBAkAbmFtZV9oYXNozeGe3/7s5fcDCgBuZXR3b3JrX2lkj/iBnAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:polished_blackstone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQRAgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tzBAkAbmFtZV9oYXNoIHgsgIdzKXcDCgBuZXR3b3JrX2lkUw9b3woGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:cracked_polished_blackstone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQXAgAACAQAbmFtZSwAbWluZWNyYWZ0OmNyYWNrZWRfcG9saXNoZWRfYmxhY2tzdG9uZV9icmlja3MECQBuYW1lX2hhc2jQIO1GQDk80AMKAG5ldHdvcmtfaWQ3UlRYCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:gilded_blackstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAgAACAQAbmFtZRsAbWluZWNyYWZ0OmdpbGRlZF9ibGFja3N0b25lBAkAbmFtZV9oYXNoNoWt1ocG0HEDCgBuZXR3b3JrX2lktL8gUwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:chiseled_polished_blackstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQWAgAACAQAbmFtZSYAbWluZWNyYWZ0OmNoaXNlbGVkX3BvbGlzaGVkX2JsYWNrc3RvbmUECQBuYW1lX2hhc2gzFa+kEjCJgAMKAG5ldHdvcmtfaWR2NJX2CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:deepslate_tiles", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlcwQJAG5hbWVfaGFzaGcLLx3NXAFvAwoAbmV0d29ya19pZI/G/xYKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:cracked_deepslate_tiles", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSYAgAACAQAbmFtZSEAbWluZWNyYWZ0OmNyYWNrZWRfZGVlcHNsYXRlX3RpbGVzBAkAbmFtZV9oYXNo9zWgkFuMM1QDCgBuZXR3b3JrX2lkGwY6OgoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:deepslate_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSGAgAACAQAbmFtZRoAbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja3MECQBuYW1lX2hhc2gucvFmPdZxigMKAG5ldHdvcmtfaWSH4HDPCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:cracked_deepslate_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSZAgAACAQAbmFtZSIAbWluZWNyYWZ0OmNyYWNrZWRfZGVlcHNsYXRlX2JyaWNrcwQJAG5hbWVfaGFzaN40aqhh9WqHAwoAbmV0d29ya19pZO9GPBQKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:chiseled_deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAgAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaEU7/uRG8HSBAwoAbmV0d29ya19pZEqmI0EKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:cobblestone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQEAAAACAQAbmFtZRUAbWluZWNyYWZ0OmNvYmJsZXN0b25lBAkAbmFtZV9oYXNoPoK7mGlSUz4DCgBuZXR3b3JrX2lkLm7RZwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:mossy_cobblestone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQwAAAACAQAbmFtZRsAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lBAkAbmFtZV9oYXNoGJ67FCbkChMDCgBuZXR3b3JrX2lk/pYs1AoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:cobbled_deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR6AgAACAQAbmFtZRsAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlBAkAbmFtZV9oYXNoLUz9Y/ywmLwDCgBuZXR3b3JrX2lkNwzZ+AoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:smooth_stone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AQAACAQAbmFtZRYAbWluZWNyYWZ0OnNtb290aF9zdG9uZQQJAG5hbWVfaGFzaMwf87/JaTNvAwoAbmV0d29ya19pZLkZICEKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZPsXMaQKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:chiseled_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvBAAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX3NhbmRzdG9uZQQJAG5hbWVfaGFzaPEkxMvZmemgAwoAbmV0d29ya19pZGI5NB4KBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:cut_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSwBAAACAQAbmFtZRcAbWluZWNyYWZ0OmN1dF9zYW5kc3RvbmUECQBuYW1lX2hhc2ichLQc71njnQMKAG5ldHdvcmtfaWSmBLkRCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:smooth_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSxBAAACAQAbmFtZRoAbWluZWNyYWZ0OnNtb290aF9zYW5kc3RvbmUECQBuYW1lX2hhc2huR7XTwISyCAMKAG5ldHdvcmtfaWSzWj3UCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:red_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWRXRYxZCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:chiseled_red_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS7BAAACAQAbmFtZSAAbWluZWNyYWZ0OmNoaXNlbGVkX3JlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2gh5sX+ON054wMKAG5ldHdvcmtfaWT6Pw1PCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:cut_red_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS8BAAACAQAbmFtZRsAbWluZWNyYWZ0OmN1dF9yZWRfc2FuZHN0b25lBAkAbmFtZV9oYXNoaOtka4NrQ1EDCgBuZXR3b3JrX2lk3r/JPAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:smooth_red_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS9BAAACAQAbmFtZR4AbWluZWNyYWZ0OnNtb290aF9yZWRfc2FuZHN0b25lBAkAbmFtZV9oYXNoqsNl8x36ju4DCgBuZXR3b3JrX2lk7x5DTwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:coal_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWStAAAACAQAbmFtZRQAbWluZWNyYWZ0OmNvYWxfYmxvY2sECQBuYW1lX2hhc2jH8QQP3t5PiAMKAG5ldHdvcmtfaWRo+sR+CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:dried_kelp_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAQAACAQAbmFtZRoAbWluZWNyYWZ0OmRyaWVkX2tlbHBfYmxvY2sECQBuYW1lX2hhc2iRoucexkrl8wMKAG5ldHdvcmtfaWQQCCrvCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:gold_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQpAAAACAQAbmFtZRQAbWluZWNyYWZ0OmdvbGRfYmxvY2sECQBuYW1lX2hhc2iYLshvjtXzFwMKAG5ldHdvcmtfaWTDJGBcCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:iron_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQqAAAACAQAbmFtZRQAbWluZWNyYWZ0Omlyb25fYmxvY2sECQBuYW1lX2hhc2jYINmJQbvV/gMKAG5ldHdvcmtfaWRf7AbICgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:copper_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRTAgAACAQAbmFtZRYAbWluZWNyYWZ0OmNvcHBlcl9ibG9jawQJAG5hbWVfaGFzaDVxnehsGaZ1AwoAbmV0d29ya19pZIiUodwKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:copper_door" + }, + { + "id": "minecraft:copper_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQXBAAACAQAbmFtZRkAbWluZWNyYWZ0OmNvcHBlcl90cmFwZG9vcgQJAG5hbWVfaGFzaO9fXio+svKVAwoAbmV0d29ya19pZMCoRjEKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:copper_grate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT/AwAACAQAbmFtZRYAbWluZWNyYWZ0OmNvcHBlcl9ncmF0ZQQJAG5hbWVfaGFzaC/JEFOWnmEcAwoAbmV0d29ya19pZC6YiiMKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:exposed_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRUAgAACAQAbmFtZRgAbWluZWNyYWZ0OmV4cG9zZWRfY29wcGVyBAkAbmFtZV9oYXNoQH3Fukmu3CEDCgBuZXR3b3JrX2lk72jFIwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:exposed_copper_door" + }, + { + "id": "minecraft:exposed_copper_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYBAAACAQAbmFtZSEAbWluZWNyYWZ0OmV4cG9zZWRfY29wcGVyX3RyYXBkb29yBAkAbmFtZV9oYXNoYhDFUysN7qUDCgBuZXR3b3JrX2lkMzwGJgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:exposed_copper_grate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQABAAACAQAbmFtZR4AbWluZWNyYWZ0OmV4cG9zZWRfY29wcGVyX2dyYXRlBAkAbmFtZV9oYXNolFIBYLYU0IcDCgBuZXR3b3JrX2lk4UqptAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:weathered_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRVAgAACAQAbmFtZRoAbWluZWNyYWZ0OndlYXRoZXJlZF9jb3BwZXIECQBuYW1lX2hhc2hJCQXbvobv+gMKAG5ldHdvcmtfaWQwM0lJCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:weathered_copper_door" + }, + { + "id": "minecraft:weathered_copper_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQZBAAACAQAbmFtZSMAbWluZWNyYWZ0OndlYXRoZXJlZF9jb3BwZXJfdHJhcGRvb3IECQBuYW1lX2hhc2hFnEC282a1tgMKAG5ldHdvcmtfaWTk70oiCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:weathered_copper_grate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBBAAACAQAbmFtZSAAbWluZWNyYWZ0OndlYXRoZXJlZF9jb3BwZXJfZ3JhdGUECQBuYW1lX2hhc2jB3o8enlv1RgMKAG5ldHdvcmtfaWRih2pOCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:oxidized_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRWAgAACAQAbmFtZRkAbWluZWNyYWZ0Om94aWRpemVkX2NvcHBlcgQJAG5hbWVfaGFzaMDtJqR0G5Y7AwoAbmV0d29ya19pZGjN8bUKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:oxidized_copper_door" + }, + { + "id": "minecraft:oxidized_copper_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQaBAAACAQAbmFtZSIAbWluZWNyYWZ0Om94aWRpemVkX2NvcHBlcl90cmFwZG9vcgQJAG5hbWVfaGFzaOJpG/XFexVwAwoAbmV0d29ya19pZPhi0J4KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:oxidized_copper_grate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCBAAACAQAbmFtZR8AbWluZWNyYWZ0Om94aWRpemVkX2NvcHBlcl9ncmF0ZQQJAG5hbWVfaGFzaBRfNhyndve7AwoAbmV0d29ya19pZKY2cnEKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:waxed_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRXAgAACAQAbmFtZRYAbWluZWNyYWZ0OndheGVkX2NvcHBlcgQJAG5hbWVfaGFzaPF+FG6Eh5fsAwoAbmV0d29ya19pZIjtz/0KBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:waxed_copper_door" + }, + { + "id": "minecraft:waxed_copper_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQbBAAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX2NvcHBlcl90cmFwZG9vcgQJAG5hbWVfaGFzaO0JUKUHqNU6AwoAbmV0d29ya19pZJC3ZuMKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:waxed_copper_grate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDBAAACAQAbmFtZRwAbWluZWNyYWZ0OndheGVkX2NvcHBlcl9ncmF0ZQQJAG5hbWVfaGFzaDmC92M2RO+HAwoAbmV0d29ya19pZH4og2AKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:waxed_exposed_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRYAgAACAQAbmFtZR4AbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY29wcGVyBAkAbmFtZV9oYXNoig8IOc+SCikDCgBuZXR3b3JrX2lklz8yWQoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:waxed_exposed_copper_door" + }, + { + "id": "minecraft:waxed_exposed_copper_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQcBAAACAQAbmFtZScAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY29wcGVyX3RyYXBkb29yBAkAbmFtZV9oYXNoBHHxCpkUzpgDCgBuZXR3b3JrX2lkw2XBGQoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:waxed_exposed_copper_grate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQEBAAACAQAbmFtZSQAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY29wcGVyX2dyYXRlBAkAbmFtZV9oYXNoWmd6B+hWwiEDCgBuZXR3b3JrX2lk8d4ZQwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:waxed_weathered_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRZAgAACAQAbmFtZSAAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jb3BwZXIECQBuYW1lX2hhc2gjtPq8MOdvKgMKAG5ldHdvcmtfaWSQ9Ln9CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:waxed_weathered_copper_door" + }, + { + "id": "minecraft:waxed_weathered_copper_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQdBAAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jb3BwZXJfdHJhcGRvb3IECQBuYW1lX2hhc2gH9Fi3JCF4egMKAG5ldHdvcmtfaWRkGU6TCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:waxed_weathered_copper_grate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQFBAAACAQAbmFtZSYAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jb3BwZXJfZ3JhdGUECQBuYW1lX2hhc2hXfilVFDAiYQMKAG5ldHdvcmtfaWQqTGC1CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:waxed_oxidized_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS9AgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NvcHBlcgQJAG5hbWVfaGFzaMaORhsO+LzjAwoAbmV0d29ya19pZJhGfLEKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:waxed_oxidized_copper_door" + }, + { + "id": "minecraft:waxed_oxidized_copper_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQeBAAACAQAbmFtZSgAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NvcHBlcl90cmFwZG9vcgQJAG5hbWVfaGFzaNA/q9qAy6Z9AwoAbmV0d29ya19pZDgExS8KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:waxed_oxidized_copper_grate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGBAAACAQAbmFtZSUAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NvcHBlcl9ncmF0ZQQJAG5hbWVfaGFzaEbeMT605GP4AwoAbmV0d29ya19pZOZjpkkKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRaAgAACAQAbmFtZRQAbWluZWNyYWZ0OmN1dF9jb3BwZXIECQBuYW1lX2hhc2hAfN3NGax3eAMKAG5ldHdvcmtfaWTnFBtYCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:exposed_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRbAgAACAQAbmFtZRwAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcgQJAG5hbWVfaGFzaA85G3yv/w6pAwoAbmV0d29ya19pZMQhr0QKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:weathered_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRcAgAACAQAbmFtZR4AbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyBAkAbmFtZV9oYXNoVgRV0fBaz88DCgBuZXR3b3JrX2lk/0cYugoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:oxidized_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRdAgAACAQAbmFtZR0AbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2iP8WmFWOkriwMKAG5ldHdvcmtfaWQPdce7CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:waxed_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWReAgAACAQAbmFtZRoAbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2jumiwOZIqv2AMKAG5ldHdvcmtfaWQvuxx9CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:waxed_exposed_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRfAgAACAQAbmFtZSIAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcgQJAG5hbWVfaGFzaPE/OfK6IoVMAwoAbmV0d29ya19pZHy5HkcKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:waxed_weathered_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRgAgAACAQAbmFtZSQAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyBAkAbmFtZV9oYXNoCA1xDp11bnwDCgBuZXR3b3JrX2lkDyEDVQoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:waxed_oxidized_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS+AgAACAQAbmFtZSMAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2i1pZAsZYHLDAMKAG5ldHdvcmtfaWQ/wSkCCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:chiseled_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT3AwAACAQAbmFtZRkAbWluZWNyYWZ0OmNoaXNlbGVkX2NvcHBlcgQJAG5hbWVfaGFzaIsW5pmpJEuQAwoAbmV0d29ya19pZHetwrkKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:exposed_chiseled_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT4AwAACAQAbmFtZSEAbWluZWNyYWZ0OmV4cG9zZWRfY2hpc2VsZWRfY29wcGVyBAkAbmFtZV9oYXNoOvrLJ0UowbgDCgBuZXR3b3JrX2lkZj7cPwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:weathered_chiseled_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT5AwAACAQAbmFtZSMAbWluZWNyYWZ0OndlYXRoZXJlZF9jaGlzZWxlZF9jb3BwZXIECQBuYW1lX2hhc2hh+42XlsWvGAMKAG5ldHdvcmtfaWS7Cy59CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:oxidized_chiseled_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT6AwAACAQAbmFtZSIAbWluZWNyYWZ0Om94aWRpemVkX2NoaXNlbGVkX2NvcHBlcgQJAG5hbWVfaGFzaLpTIsnfluiCAwoAbmV0d29ya19pZB9/jS8KBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:waxed_chiseled_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT7AwAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX2NoaXNlbGVkX2NvcHBlcgQJAG5hbWVfaGFzaFnXvXY5OinzAwoAbmV0d29ya19pZAcKtHsKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:waxed_exposed_chiseled_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT8AwAACAQAbmFtZScAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY2hpc2VsZWRfY29wcGVyBAkAbmFtZV9oYXNoHJdq+Pph6hMDCgBuZXR3b3JrX2lkdge7IAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:waxed_oxidized_chiseled_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT9AwAACAQAbmFtZSgAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NoaXNlbGVkX2NvcHBlcgQJAG5hbWVfaGFzaMj49OvlTpgCAwoAbmV0d29ya19pZN/r+roKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:waxed_weathered_chiseled_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT+AwAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jaGlzZWxlZF9jb3BwZXIECQBuYW1lX2hhc2hzuO+Sg9LYQwMKAG5ldHdvcmtfaWQ7AN7iCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:copper_bulb", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHBAAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcHBlcl9idWxiBAkAbmFtZV9oYXNo41TimHOsMWcDCgBuZXR3b3JrX2lkJnZvAgoGAHN0YXRlcwEDAGxpdAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:exposed_copper_bulb", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQIBAAACAQAbmFtZR0AbWluZWNyYWZ0OmV4cG9zZWRfY29wcGVyX2J1bGIECQBuYW1lX2hhc2g++f1wYLLCrAMKAG5ldHdvcmtfaWRLdMmGCgYAc3RhdGVzAQMAbGl0AAELAHBvd2VyZWRfYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:weathered_copper_bulb", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQJBAAACAQAbmFtZR8AbWluZWNyYWZ0OndlYXRoZXJlZF9jb3BwZXJfYnVsYgQJAG5hbWVfaGFzaMEtsYfwRTXlAwoAbmV0d29ya19pZAp51LQKBgBzdGF0ZXMBAwBsaXQAAQsAcG93ZXJlZF9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:oxidized_copper_bulb", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQKBAAACAQAbmFtZR4AbWluZWNyYWZ0Om94aWRpemVkX2NvcHBlcl9idWxiBAkAbmFtZV9oYXNovnrBQZs8nDIDCgBuZXR3b3JrX2lkPsj0AAoGAHN0YXRlcwEDAGxpdAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:waxed_copper_bulb", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQLBAAACAQAbmFtZRsAbWluZWNyYWZ0OndheGVkX2NvcHBlcl9idWxiBAkAbmFtZV9oYXNoGTg6TYllMiIDCgBuZXR3b3JrX2lk9m0WhgoGAHN0YXRlcwEDAGxpdAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:waxed_exposed_copper_bulb", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQMBAAACAQAbmFtZSMAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY29wcGVyX2J1bGIECQBuYW1lX2hhc2gI6xkPcvBDVwMKAG5ldHdvcmtfaWR7BRcACgYAc3RhdGVzAQMAbGl0AAELAHBvd2VyZWRfYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:waxed_weathered_copper_bulb", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQNBAAACAQAbmFtZSUAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jb3BwZXJfYnVsYgQJAG5hbWVfaGFzaMsUnmp3/VqVAwoAbmV0d29ya19pZEoworoKBgBzdGF0ZXMBAwBsaXQAAQsAcG93ZXJlZF9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:waxed_oxidized_copper_bulb", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQOBAAACAQAbmFtZSQAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NvcHBlcl9idWxiBAkAbmFtZV9oYXNoBFKxY3fjVq4DCgBuZXR3b3JrX2lkzrJ6aAoGAHN0YXRlcwEDAGxpdAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:emerald_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAAAACAQAbmFtZRcAbWluZWNyYWZ0OmVtZXJhbGRfYmxvY2sECQBuYW1lX2hhc2hK6QunqJznNAMKAG5ldHdvcmtfaWRk5+otCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:diamond_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ5AAAACAQAbmFtZRcAbWluZWNyYWZ0OmRpYW1vbmRfYmxvY2sECQBuYW1lX2hhc2iGKrxuvkytFQMKAG5ldHdvcmtfaWQQeQZXCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:lapis_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQWAAAACAQAbmFtZRUAbWluZWNyYWZ0OmxhcGlzX2Jsb2NrBAkAbmFtZV9oYXNoDZ44xdb2zVoDCgBuZXR3b3JrX2lktVy0BAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:raw_iron_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTCAgAACAQAbmFtZRgAbWluZWNyYWZ0OnJhd19pcm9uX2Jsb2NrBAkAbmFtZV9oYXNo9XyzNIQXxvwDCgBuZXR3b3JrX2lknms1QAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:raw_copper_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTDAgAACAQAbmFtZRoAbWluZWNyYWZ0OnJhd19jb3BwZXJfYmxvY2sECQBuYW1lX2hhc2hw1KG0TNUGgwMKAG5ldHdvcmtfaWS1vGo/CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:raw_gold_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTEAgAACAQAbmFtZRgAbWluZWNyYWZ0OnJhd19nb2xkX2Jsb2NrBAkAbmFtZV9oYXNo6YuwuLwfOBwDCgBuZXR3b3JrX2lkLiQ5gQoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:quartz_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAAAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZE2axGsKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:quartz_pillar", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS5BAAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9waWxsYXIECQBuYW1lX2hhc2igp62HI+PuSwMKAG5ldHdvcmtfaWS9SGXLCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:chiseled_quartz_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS4BAAACAQAbmFtZR8AbWluZWNyYWZ0OmNoaXNlbGVkX3F1YXJ0el9ibG9jawQJAG5hbWVfaGFzaAftJM9mCAvaAwoAbmV0d29ya19pZFwy0s0KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:smooth_quartz", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS6BAAACAQAbmFtZRcAbWluZWNyYWZ0OnNtb290aF9xdWFydHoECQBuYW1lX2hhc2hIVzzgiItGagMKAG5ldHdvcmtfaWTVWgU2CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:prismarine", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAAAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWQnuuW1CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:dark_prismarine", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSyBAAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfcHJpc21hcmluZQQJAG5hbWVfaGFzaK+rhxsgkzplAwoAbmV0d29ya19pZIdA0I0KBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:slime", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAAAACAQAbmFtZQ8AbWluZWNyYWZ0OnNsaW1lBAkAbmFtZV9oYXNoHJiEEJx+JlkDCgBuZXR3b3JrX2lkfgfVzAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:honey_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTbAQAACAQAbmFtZRUAbWluZWNyYWZ0OmhvbmV5X2Jsb2NrBAkAbmFtZV9oYXNo9zLYSUlelywDCgBuZXR3b3JrX2lko+dyWgoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:honeycomb_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAQAACAQAbmFtZRkAbWluZWNyYWZ0OmhvbmV5Y29tYl9ibG9jawQJAG5hbWVfaGFzaASIPuOCYd1oAwoAbmV0d29ya19pZKys4n4KBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:hay_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAAAACAQAbmFtZRMAbWluZWNyYWZ0OmhheV9ibG9jawQJAG5hbWVfaGFzaIB2VxKxX8EpAwoAbmV0d29ya19pZKuQSloKBgBzdGF0ZXMDCgBkZXByZWNhdGVkAAAAAAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:bone_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTYAAAACAQAbmFtZRQAbWluZWNyYWZ0OmJvbmVfYmxvY2sECQBuYW1lX2hhc2i4ZX576W9AWgMKAG5ldHdvcmtfaWTWGacQCgYAc3RhdGVzAwoAZGVwcmVjYXRlZAAAAAAICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:nether_brick", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRwAAAACAQAbmFtZRYAbWluZWNyYWZ0Om5ldGhlcl9icmljawQJAG5hbWVfaGFzaMxcRiheU+nXAwoAbmV0d29ya19pZMkmzloKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:red_nether_brick", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAAAACAQAbmFtZRoAbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2sECQBuYW1lX2hhc2j8pRO4LfoECAMKAG5ldHdvcmtfaWRpdF0YCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:netherite_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQNAgAACAQAbmFtZRkAbWluZWNyYWZ0Om5ldGhlcml0ZV9ibG9jawQJAG5hbWVfaGFzaMghh6Zib/ZKAwoAbmV0d29ya19pZIz0mq0KBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:lodestone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAQAACAQAbmFtZRMAbWluZWNyYWZ0OmxvZGVzdG9uZQQJAG5hbWVfaGFzaJ2gmHOTlXv8AwoAbmV0d29ya19pZEfgB4wKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:white_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQjAAAACAQAbmFtZRQAbWluZWNyYWZ0OndoaXRlX3dvb2wECQBuYW1lX2hhc2jRWB7vaIEDiQMKAG5ldHdvcmtfaWSO8paQCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:light_gray_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQnAwAACAQAbmFtZRkAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfd29vbAQJAG5hbWVfaGFzaOpdQ1a2v4b3AwoAbmV0d29ya19pZIqZCYEKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:gray_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQoAwAACAQAbmFtZRMAbWluZWNyYWZ0OmdyYXlfd29vbAQJAG5hbWVfaGFzaLsc1Lp1xdIOAwoAbmV0d29ya19pZFUs+HgKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:black_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQpAwAACAQAbmFtZRQAbWluZWNyYWZ0OmJsYWNrX3dvb2wECQBuYW1lX2hhc2hP2HC6o0X4HAMKAG5ldHdvcmtfaWRUbORcCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:brown_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQqAwAACAQAbmFtZRQAbWluZWNyYWZ0OmJyb3duX3dvb2wECQBuYW1lX2hhc2ig5IW89PrREwMKAG5ldHdvcmtfaWRjT9j8CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:red_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQrAwAACAQAbmFtZRIAbWluZWNyYWZ0OnJlZF93b29sBAkAbmFtZV9oYXNoY4TBDq+mFgUDCgBuZXR3b3JrX2lktn9lcAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:orange_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAwAACAQAbmFtZRUAbWluZWNyYWZ0Om9yYW5nZV93b29sBAkAbmFtZV9oYXNoFstfrTZfSCgDCgBuZXR3b3JrX2lk+rqywwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:yellow_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQtAwAACAQAbmFtZRUAbWluZWNyYWZ0OnllbGxvd193b29sBAkAbmFtZV9oYXNoTFyus2RHegcDCgBuZXR3b3JrX2lkkKBhXAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:lime_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQuAwAACAQAbmFtZRMAbWluZWNyYWZ0OmxpbWVfd29vbAQJAG5hbWVfaGFzaNVnnzKiMxmeAwoAbmV0d29ya19pZG9b32kKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:green_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQvAwAACAQAbmFtZRQAbWluZWNyYWZ0OmdyZWVuX3dvb2wECQBuYW1lX2hhc2i3mElRYHIcSQMKAG5ldHdvcmtfaWSssprwCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:cyan_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQwAwAACAQAbmFtZRMAbWluZWNyYWZ0OmN5YW5fd29vbAQJAG5hbWVfaGFzaBNDfvHn8dqFAwoAbmV0d29ya19pZK0hAbgKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:light_blue_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQxAwAACAQAbmFtZRkAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfd29vbAQJAG5hbWVfaGFzaLWFAUfyxFPNAwoAbmV0d29ya19pZL2oEugKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:blue_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQyAwAACAQAbmFtZRMAbWluZWNyYWZ0OmJsdWVfd29vbAQJAG5hbWVfaGFzaLjHyxxbTWCLAwoAbmV0d29ya19pZPaLdFQKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:purple_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQzAwAACAQAbmFtZRUAbWluZWNyYWZ0OnB1cnBsZV93b29sBAkAbmFtZV9oYXNojvFtqzjAf/4DCgBuZXR3b3JrX2lklqASNQoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:magenta_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ0AwAACAQAbmFtZRYAbWluZWNyYWZ0Om1hZ2VudGFfd29vbAQJAG5hbWVfaGFzaGuOHvf+Pd4yAwoAbmV0d29ya19pZI4UoDQKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:pink_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ1AwAACAQAbmFtZRMAbWluZWNyYWZ0OnBpbmtfd29vbAQJAG5hbWVfaGFzaPiVA2pFeoFLAwoAbmV0d29ya19pZOZRO6oKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:white_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAAAACAQAbmFtZRYAbWluZWNyYWZ0OndoaXRlX2NhcnBldAQJAG5hbWVfaGFzaNeMHTI1fWPXAwoAbmV0d29ya19pZEahDFcKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:light_gray_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRbAwAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY2FycGV0BAkAbmFtZV9oYXNoHPw6ArBAsP0DCgBuZXR3b3JrX2lkQoAeUAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:gray_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRaAwAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXlfY2FycGV0BAkAbmFtZV9oYXNoZVR0OI+1VRADCgBuZXR3b3JrX2lkETF4WwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:black_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJsYWNrX2NhcnBldAQJAG5hbWVfaGFzaOk7LP9NptyhAwoAbmV0d29ya19pZFjmXtIKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:brown_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRfAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJyb3duX2NhcnBldAQJAG5hbWVfaGFzaNaXFyOsAvIvAwoAbmV0d29ya19pZHPjFuoKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:red_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAwAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9jYXJwZXQECQBuYW1lX2hhc2i9eSKBf6SO3wMKAG5ldHdvcmtfaWQuhI/KCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:orange_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRUAwAACAQAbmFtZRcAbWluZWNyYWZ0Om9yYW5nZV9jYXJwZXQECQBuYW1lX2hhc2hIUkO4HlAdygMKAG5ldHdvcmtfaWSyKV9OCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:yellow_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRXAwAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19jYXJwZXQECQBuYW1lX2hhc2hSDKX3scCamwMKAG5ldHdvcmtfaWT8nq+ECgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:lime_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRYAwAACAQAbmFtZRUAbWluZWNyYWZ0OmxpbWVfY2FycGV0BAkAbmFtZV9oYXNo+6KFOpzsib4DCgBuZXR3b3JrX2lkT+DS4woGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:green_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRgAwAACAQAbmFtZRYAbWluZWNyYWZ0OmdyZWVuX2NhcnBldAQJAG5hbWVfaGFzaCHPMP9ltqFJAwoAbmV0d29ya19pZBgwAvAKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:cyan_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRcAwAACAQAbmFtZRUAbWluZWNyYWZ0OmN5YW5fY2FycGV0BAkAbmFtZV9oYXNobXf62dQBJj8DCgBuZXR3b3JrX2lkKVppLgoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:light_blue_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRWAwAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY2FycGV0BAkAbmFtZV9oYXNo20l4oktdZ3sDCgBuZXR3b3JrX2lkjdeMiwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:blue_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWReAwAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfY2FycGV0BAkAbmFtZV9oYXNo3p3lsW0eQwsDCgBuZXR3b3JrX2lkAovdPQoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:purple_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRdAwAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnBsZV9jYXJwZXQECQBuYW1lX2hhc2jwIA9pW/qp7QMKAG5ldHdvcmtfaWTqJqhjCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:magenta_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRVAwAACAQAbmFtZRgAbWluZWNyYWZ0Om1hZ2VudGFfY2FycGV0BAkAbmFtZV9oYXNoFXT36YNNZhMDCgBuZXR3b3JrX2lk+tqsGAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:pink_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRZAwAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfY2FycGV0BAkAbmFtZV9oYXNoHll72oqk+OoDCgBuZXR3b3JrX2lkrnBYDwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:white_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTtAAAACAQAbmFtZR8AbWluZWNyYWZ0OndoaXRlX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaFUk9iXVjwV8AwoAbmV0d29ya19pZJPZY8AKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:light_gray_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAwAACAQAbmFtZSQAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNo7EUk30hmUtYDCgBuZXR3b3JrX2lkh8jVIwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:gray_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTKAwAACAQAbmFtZR4AbWluZWNyYWZ0OmdyYXlfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoW77af6WihdwDCgBuZXR3b3JrX2lkSsqC1woGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:black_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTSAwAACAQAbmFtZR8AbWluZWNyYWZ0OmJsYWNrX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaAfWYp0xtgcfAwoAbmV0d29ya19pZMWTC8EKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:brown_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTPAwAACAQAbmFtZR8AbWluZWNyYWZ0OmJyb3duX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaB74EeiLO46XAwoAbmV0d29ya19pZEDHKqwKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:red_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTRAwAACAQAbmFtZR0AbWluZWNyYWZ0OnJlZF9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2gjFut6Z/VH1gMKAG5ldHdvcmtfaWSvcmwYCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:orange_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTEAwAACAQAbmFtZSAAbWluZWNyYWZ0Om9yYW5nZV9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2gADDj2IJiw+gMKAG5ldHdvcmtfaWTHph0FCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:yellow_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTHAwAACAQAbmFtZSAAbWluZWNyYWZ0OnllbGxvd19jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2iy6qKNn3ob5wMKAG5ldHdvcmtfaWQZAI39CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:lime_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTIAwAACAQAbmFtZR4AbWluZWNyYWZ0OmxpbWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNo4dYIPslbXPUDCgBuZXR3b3JrX2lk2O8X0AoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:green_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTQAwAACAQAbmFtZR8AbWluZWNyYWZ0OmdyZWVuX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaM/c9x2aJh3HAwoAbmV0d29ya19pZA0VfBMKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:cyan_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTMAwAACAQAbmFtZR4AbWluZWNyYWZ0OmN5YW5fY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNok+xKAe7XXjoDCgBuZXR3b3JrX2lkmkn6uwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:light_blue_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTGAwAACAQAbmFtZSQAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNogScpIQceyAEDCgBuZXR3b3JrX2lkOmVSbgoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:blue_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTOAwAACAQAbmFtZR4AbWluZWNyYWZ0OmJsdWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoFp7mmeL86r0DCgBuZXR3b3JrX2lkS3b3RQoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:purple_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTNAwAACAQAbmFtZSAAbWluZWNyYWZ0OnB1cnBsZV9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2iYcVU04hoStwMKAG5ldHdvcmtfaWQXimEjCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:magenta_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTFAwAACAQAbmFtZSEAbWluZWNyYWZ0Om1hZ2VudGFfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoy/70q6VPsWgDCgBuZXR3b3JrX2lkf9mxQwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:pink_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAwAACAQAbmFtZR4AbWluZWNyYWZ0OnBpbmtfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoVikSAf8DwV0DCgBuZXR3b3JrX2lku2MivwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:white_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTsAAAACAQAbmFtZRgAbWluZWNyYWZ0OndoaXRlX2NvbmNyZXRlBAkAbmFtZV9oYXNo6zAp7lsLlvkDCgBuZXR3b3JrX2lk3MAYQAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:light_gray_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR6AwAACAQAbmFtZR0AbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY29uY3JldGUECQBuYW1lX2hhc2hEtet5wuDIKAMKAG5ldHdvcmtfaWQISs02CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:gray_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR5AwAACAQAbmFtZRcAbWluZWNyYWZ0OmdyYXlfY29uY3JldGUECQBuYW1lX2hhc2j92INnb0a83AMKAG5ldHdvcmtfaWQj8RHwCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:black_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAwAACAQAbmFtZRgAbWluZWNyYWZ0OmJsYWNrX2NvbmNyZXRlBAkAbmFtZV9oYXNo2X7NDIQmZ70DCgBuZXR3b3JrX2lk2uiVDQoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:brown_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR+AwAACAQAbmFtZRgAbWluZWNyYWZ0OmJyb3duX2NvbmNyZXRlBAkAbmFtZV9oYXNoeka02BwXf6oDCgBuZXR3b3JrX2lkYf+xDQoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:red_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSAAwAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZF9jb25jcmV0ZQQJAG5hbWVfaGFzaPWmNowLGubqAwoAbmV0d29ya19pZKwyx58KBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:orange_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRzAwAACAQAbmFtZRkAbWluZWNyYWZ0Om9yYW5nZV9jb25jcmV0ZQQJAG5hbWVfaGFzaAgE8XmaAi6+AwoAbmV0d29ya19pZMDQNz8KBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:yellow_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR2AwAACAQAbmFtZRkAbWluZWNyYWZ0OnllbGxvd19jb25jcmV0ZQQJAG5hbWVfaGFzaE6ONfJPBd0+AwoAbmV0d29ya19pZMarutwKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:lime_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR3AwAACAQAbmFtZRcAbWluZWNyYWZ0OmxpbWVfY29uY3JldGUECQBuYW1lX2hhc2gnd8JW6wmJcAMKAG5ldHdvcmtfaWTd47aoCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:green_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR/AwAACAQAbmFtZRgAbWluZWNyYWZ0OmdyZWVuX2NvbmNyZXRlBAkAbmFtZV9oYXNokbFxRKchQZkDCgBuZXR3b3JrX2lkmhZWUgoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:cyan_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR7AwAACAQAbmFtZRcAbWluZWNyYWZ0OmN5YW5fY29uY3JldGUECQBuYW1lX2hhc2hFRrWJ33qj1wMKAG5ldHdvcmtfaWQbi5b8CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:light_blue_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR1AwAACAQAbmFtZR0AbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY29uY3JldGUECQBuYW1lX2hhc2gHAe0kl0SE4AMKAG5ldHdvcmtfaWRL/GbSCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:blue_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR9AwAACAQAbmFtZRcAbWluZWNyYWZ0OmJsdWVfY29uY3JldGUECQBuYW1lX2hhc2hiay301nnj1wMKAG5ldHdvcmtfaWRMvFXNCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:purple_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR8AwAACAQAbmFtZRkAbWluZWNyYWZ0OnB1cnBsZV9jb25jcmV0ZQQJAG5hbWVfaGFzaHBHflsPIwdXAwoAbmV0d29ya19pZCyKA5gKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:magenta_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR0AwAACAQAbmFtZRoAbWluZWNyYWZ0Om1hZ2VudGFfY29uY3JldGUECQBuYW1lX2hhc2gN7LuB/OvdZAMKAG5ldHdvcmtfaWTc6ZOdCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:pink_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR4AwAACAQAbmFtZRcAbWluZWNyYWZ0OnBpbmtfY29uY3JldGUECQBuYW1lX2hhc2ii2G5F0u3SOAMKAG5ldHdvcmtfaWSszGgrCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:clay", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRSAAAACAQAbmFtZQ4AbWluZWNyYWZ0OmNsYXkECQBuYW1lX2hhc2j/S6sKXRcpzwMKAG5ldHdvcmtfaWRmsb8nCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:hardened_clay", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSsAAAACAQAbmFtZRcAbWluZWNyYWZ0OmhhcmRlbmVkX2NsYXkECQBuYW1lX2hhc2jrnRwCJ0krJAMKAG5ldHdvcmtfaWRBCOrrCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:white_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSfAAAACAQAbmFtZRoAbWluZWNyYWZ0OndoaXRlX3RlcnJhY290dGEECQBuYW1lX2hhc2j3RSdgmnAIewMKAG5ldHdvcmtfaWSimKw+CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:light_gray_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAwAACAQAbmFtZR8AbWluZWNyYWZ0OmxpZ2h0X2dyYXlfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAz1Ri3wIxomAwoAbmV0d29ya19pZH5qgOcKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:gray_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTZAwAACAQAbmFtZRkAbWluZWNyYWZ0OmdyYXlfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAXdSLAaNZ9vAwoAbmV0d29ya19pZM1QDV0KBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:black_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWThAwAACAQAbmFtZRoAbWluZWNyYWZ0OmJsYWNrX3RlcnJhY290dGEECQBuYW1lX2hhc2jxssdv5vlbpgMKAG5ldHdvcmtfaWRE3Ru/CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:brown_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTeAwAACAQAbmFtZRoAbWluZWNyYWZ0OmJyb3duX3RlcnJhY290dGEECQBuYW1lX2hhc2gG4kPenmOF9gMKAG5ldHdvcmtfaWQ/i0iNCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:red_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAwAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNo7fX56HXFejEDCgBuZXR3b3JrX2lk8tTF8QoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:orange_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAwAACAQAbmFtZRsAbWluZWNyYWZ0Om9yYW5nZV90ZXJyYWNvdHRhBAkAbmFtZV9oYXNo0Hjmql3sruMDCgBuZXR3b3JrX2lklmqmkAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:yellow_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTWAwAACAQAbmFtZRsAbWluZWNyYWZ0OnllbGxvd190ZXJyYWNvdHRhBAkAbmFtZV9oYXNoqkyKKrmA3VcDCgBuZXR3b3JrX2lkaM/orAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:lime_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAwAACAQAbmFtZRkAbWluZWNyYWZ0OmxpbWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaANjADFOF9v7AwoAbmV0d29ya19pZJt0XsgKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:green_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAwAACAQAbmFtZRoAbWluZWNyYWZ0OmdyZWVuX3RlcnJhY290dGEECQBuYW1lX2hhc2j5Ybq36yYwRQMKAG5ldHdvcmtfaWQ8kGdHCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:cyan_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTbAwAACAQAbmFtZRkAbWluZWNyYWZ0OmN5YW5fdGVycmFjb3R0YQQJAG5hbWVfaGFzaN09COzMuHwAAwoAbmV0d29ya19pZIWPCzoKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:light_blue_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTVAwAACAQAbmFtZR8AbWluZWNyYWZ0OmxpZ2h0X2JsdWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaOMytez7cOZiAwoAbmV0d29ya19pZFHK1UsKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:blue_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAwAACAQAbmFtZRkAbWluZWNyYWZ0OmJsdWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaF6inyTK5RpAAwoAbmV0d29ya19pZF5mVZIKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:purple_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAwAACAQAbmFtZRsAbWluZWNyYWZ0OnB1cnBsZV90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoKF7YG61yTbEDCgBuZXR3b3JrX2lkhtRDlwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:magenta_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTUAwAACAQAbmFtZRwAbWluZWNyYWZ0Om1hZ2VudGFfdGVycmFjb3R0YQQJAG5hbWVfaGFzaLWvtpAVtztyAwoAbmV0d29ya19pZN5SoakKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:pink_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTYAwAACAQAbmFtZRkAbWluZWNyYWZ0OnBpbmtfdGVycmFjb3R0YQQJAG5hbWVfaGFzaJ7mzvyzSQZTAwoAbmV0d29ya19pZDJWe4YKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:white_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAAAACAQAbmFtZSEAbWluZWNyYWZ0OndoaXRlX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoiVzCdoHAJo0DCgBuZXR3b3JrX2lkIlj9AAoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:silver_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAAAACAQAbmFtZSIAbWluZWNyYWZ0OnNpbHZlcl9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAVsA0CnhzA4AwoAbmV0d29ya19pZPnxtJEKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:gray_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAAAACAQAbmFtZSAAbWluZWNyYWZ0OmdyYXlfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2jvLZt9u/lF/AMKAG5ldHdvcmtfaWQVU8eFCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:black_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTrAAAACAQAbmFtZSEAbWluZWNyYWZ0OmJsYWNrX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoe8I4xAXbO5UDCgBuZXR3b3JrX2lk2Icb9AoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:brown_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWToAAAACAQAbmFtZSEAbWluZWNyYWZ0OmJyb3duX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoSiNZOobbpjoDCgBuZXR3b3JrX2lkJy0jwgoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:red_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTqAAAACAQAbmFtZR8AbWluZWNyYWZ0OnJlZF9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaBdWFGLmCLFVAwoAbmV0d29ya19pZMYBJSEKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:orange_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAAAACAQAbmFtZSIAbWluZWNyYWZ0Om9yYW5nZV9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaMyJMrnPr7szAwoAbmV0d29ya19pZN6+7TUKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:yellow_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAAAACAQAbmFtZSIAbWluZWNyYWZ0OnllbGxvd19nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaN6NaIhf6m0uAwoAbmV0d29ya19pZKRHXeoKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:lime_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWThAAAACAQAbmFtZSAAbWluZWNyYWZ0OmxpbWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2iF3E68/rB2EAMKAG5ldHdvcmtfaWSP7qQWCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:green_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTpAAAACAQAbmFtZSEAbWluZWNyYWZ0OmdyZWVuX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNow5mo8aQDFboDCgBuZXR3b3JrX2lkoF11kgoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:cyan_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAAAACAQAbmFtZSAAbWluZWNyYWZ0OmN5YW5fZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2gnNB+cCFRJhwMKAG5ldHdvcmtfaWT9buMtCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:light_blue_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAAAACAQAbmFtZSYAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2gladnCDBKCigMKAG5ldHdvcmtfaWS5CszFCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:blue_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTnAAAACAQAbmFtZSAAbWluZWNyYWZ0OmJsdWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2giOZK+2nB1igMKAG5ldHdvcmtfaWR+e22CCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:purple_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTbAAAACAQAbmFtZSIAbWluZWNyYWZ0OnB1cnBsZV9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaIQU03txeAfHAwoAbmV0d29ya19pZLKbSE4KBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:magenta_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTeAAAACAQAbmFtZSMAbWluZWNyYWZ0Om1hZ2VudGFfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2i/SNqDJbfjMgMKAG5ldHdvcmtfaWQKf9UvCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:pink_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAAAACAQAbmFtZSAAbWluZWNyYWZ0OnBpbmtfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2hik8DVt4g+twMKAG5ldHdvcmtfaWTKzav2CgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:purpur_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAAAACAQAbmFtZRYAbWluZWNyYWZ0OnB1cnB1cl9ibG9jawQJAG5hbWVfaGFzaAgLwnUZGlzsAwoAbmV0d29ya19pZLD8ox4KBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQcAZGVmYXVsdAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:purpur_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAAAACAQAbmFtZRYAbWluZWNyYWZ0OnB1cnB1cl9ibG9jawQJAG5hbWVfaGFzaAgLwnUZGlzsAwoAbmV0d29ya19pZPSAFFsKBgBzdGF0ZXMICwBjaGlzZWxfdHlwZQUAbGluZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:packed_mud", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAgAACAQAbmFtZRQAbWluZWNyYWZ0OnBhY2tlZF9tdWQECQBuYW1lX2hhc2gHOMa121h4FgMKAG5ldHdvcmtfaWTUb6LyCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:mud_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAgAACAQAbmFtZRQAbWluZWNyYWZ0Om11ZF9icmlja3MECQBuYW1lX2hhc2iDL/SVl/PewQMKAG5ldHdvcmtfaWSkBjaDCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:nether_wart_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTWAAAACAQAbmFtZRsAbWluZWNyYWZ0Om5ldGhlcl93YXJ0X2Jsb2NrBAkAbmFtZV9oYXNo9XGS4GNnlV4DCgBuZXR3b3JrX2lkh3apIgoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:warped_wart_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAQAACAQAbmFtZRsAbWluZWNyYWZ0OndhcnBlZF93YXJ0X2Jsb2NrBAkAbmFtZV9oYXNo9IqDS9yUPJoDCgBuZXR3b3JrX2lkMpKAbAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:shroomlight", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAQAACAQAbmFtZRUAbWluZWNyYWZ0OnNocm9vbWxpZ2h0BAkAbmFtZV9oYXNoZHCHcHX/HYADCgBuZXR3b3JrX2lkLG2JiwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:crimson_nylium", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTnAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fbnlsaXVtBAkAbmFtZV9oYXNoOr6DJYW2bFYDCgBuZXR3b3JrX2lkuWpRDgoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:warped_nylium", + "block_state_b64": "CgAAAwgAYmxvY2tfaWToAQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9ueWxpdW0ECQBuYW1lX2hhc2g0Zf89cfr3rwMKAG5ldHdvcmtfaWSu/kekCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:netherrack", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRXAAAACAQAbmFtZRQAbWluZWNyYWZ0Om5ldGhlcnJhY2sECQBuYW1lX2hhc2i/r5ZyRsvPyQMKAG5ldHdvcmtfaWTAiTOACgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:basalt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTpAQAACAQAbmFtZRAAbWluZWNyYWZ0OmJhc2FsdAQJAG5hbWVfaGFzaH+UQO2yWodiAwoAbmV0d29ya19pZBPNSV4KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:polished_basalt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTqAQAACAQAbmFtZRkAbWluZWNyYWZ0OnBvbGlzaGVkX2Jhc2FsdAQJAG5hbWVfaGFzaMS+L0gMnRcBAwoAbmV0d29ya19pZF+/mHwKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:smooth_basalt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR4AgAACAQAbmFtZRcAbWluZWNyYWZ0OnNtb290aF9iYXNhbHQECQBuYW1lX2hhc2jKPUdz89kuNAMKAG5ldHdvcmtfaWTkb/oVCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:soul_soil", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTrAQAACAQAbmFtZRMAbWluZWNyYWZ0OnNvdWxfc29pbAQJAG5hbWVfaGFzaC1/87ccutuTAwoAbmV0d29ya19pZKc63SMKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:dirt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAAAACAQAbmFtZQ4AbWluZWNyYWZ0OmRpcnQECQBuYW1lX2hhc2hXp6jnXAe+kQMKAG5ldHdvcmtfaWSG706CCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:coarse_dirt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTBBAAACAQAbmFtZRUAbWluZWNyYWZ0OmNvYXJzZV9kaXJ0BAkAbmFtZV9oYXNosd+cah7WSmoDCgBuZXR3b3JrX2lkgS5RcAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:farmland", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ8AAAACAQAbmFtZRIAbWluZWNyYWZ0OmZhcm1sYW5kBAkAbmFtZV9oYXNoxyQ5ag7LolADCgBuZXR3b3JrX2lkX618FQoGAHN0YXRlcwMSAG1vaXN0dXJpemVkX2Ftb3VudAAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:grass_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAAAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXNzX2Jsb2NrBAkAbmFtZV9oYXNojPyGp3/CSZwDCgBuZXR3b3JrX2lktCgx3goGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:grass_path", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTGAAAACAQAbmFtZRQAbWluZWNyYWZ0OmdyYXNzX3BhdGgECQBuYW1lX2hhc2i0/KZV8Qsy+gMKAG5ldHdvcmtfaWT7CcdzCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:podzol", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTzAAAACAQAbmFtZRAAbWluZWNyYWZ0OnBvZHpvbAQJAG5hbWVfaGFzaBzqokRjH4Z1AwoAbmV0d29ya19pZPPS/GUKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:mycelium", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRuAAAACAQAbmFtZRIAbWluZWNyYWZ0Om15Y2VsaXVtBAkAbmFtZV9oYXNojTN09cKickIDCgBuZXR3b3JrX2lkLNPxXQoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:mud", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTYAgAACAQAbmFtZQ0AbWluZWNyYWZ0Om11ZAQJAG5hbWVfaGFzaPb/3P+uLy+9AwoAbmV0d29ya19pZPIUlUkKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:stone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAAAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lkIQ4xgAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:iron_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQPAAAACAQAbmFtZRIAbWluZWNyYWZ0Omlyb25fb3JlBAkAbmFtZV9oYXNoS7BYtLnfx3gDCgBuZXR3b3JrX2lk3loneQoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:gold_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQOAAAACAQAbmFtZRIAbWluZWNyYWZ0OmdvbGRfb3JlBAkAbmFtZV9oYXNoC5Y+DUGXLC4DCgBuZXR3b3JrX2lkNhvMfwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:diamond_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ4AAAACAQAbmFtZRUAbWluZWNyYWZ0OmRpYW1vbmRfb3JlBAkAbmFtZV9oYXNokUOJ2wZZrGQDCgBuZXR3b3JrX2lk/dChVAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:lapis_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQVAAAACAQAbmFtZRMAbWluZWNyYWZ0OmxhcGlzX29yZQQJAG5hbWVfaGFzaMrmrUrSzb7qAwoAbmV0d29ya19pZMg+qK4KBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:redstone_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRJAAAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZHN0b25lX29yZQQJAG5hbWVfaGFzaFHVnp8Wc4JbAwoAbmV0d29ya19pZKDYvQoKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:coal_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQQAAAACAQAbmFtZRIAbWluZWNyYWZ0OmNvYWxfb3JlBAkAbmFtZV9oYXNo1OjA+Iuy51oDCgBuZXR3b3JrX2lk+R/aKAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:copper_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ2AgAACAQAbmFtZRQAbWluZWNyYWZ0OmNvcHBlcl9vcmUECQBuYW1lX2hhc2iSZduSntOzOwMKAG5ldHdvcmtfaWQtIuCnCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:emerald_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAAAACAQAbmFtZRUAbWluZWNyYWZ0OmVtZXJhbGRfb3JlBAkAbmFtZV9oYXNoJTovr+VgINsDCgBuZXR3b3JrX2lknbkqCgoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:quartz_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSZAAAACAQAbmFtZRQAbWluZWNyYWZ0OnF1YXJ0el9vcmUECQBuYW1lX2hhc2g0yNHLMK9TaQMKAG5ldHdvcmtfaWSzN7nzCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:nether_gold_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQfAgAACAQAbmFtZRkAbWluZWNyYWZ0Om5ldGhlcl9nb2xkX29yZQQJAG5hbWVfaGFzaEJZ7segIBgBAwoAbmV0d29ya19pZNI9pDgKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:ancient_debris", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQOAgAACAQAbmFtZRgAbWluZWNyYWZ0OmFuY2llbnRfZGVicmlzBAkAbmFtZV9oYXNoNrbxMc9AwKcDCgBuZXR3b3JrX2lkrSNjEAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:deepslate_iron_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSQAgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9pcm9uX29yZQQJAG5hbWVfaGFzaB/fDL9pgvXXAwoAbmV0d29ya19pZFA0bz4KBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:deepslate_gold_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9nb2xkX29yZQQJAG5hbWVfaGFzaF9G7WYhKFinAwoAbmV0d29ya19pZHQTfBUKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:deepslate_diamond_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSUAgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV9kaWFtb25kX29yZQQJAG5hbWVfaGFzaEUH5USh+iD3AwoAbmV0d29ya19pZHP6VzAKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:deepslate_lapis_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV9sYXBpc19vcmUECQBuYW1lX2hhc2j+yFxU/KZs1gMKAG5ldHdvcmtfaWRKINzICgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:deepslate_redstone_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSSAgAACAQAbmFtZSAAbWluZWNyYWZ0OmRlZXBzbGF0ZV9yZWRzdG9uZV9vcmUECQBuYW1lX2hhc2iVgM3wWWD6ugMKAG5ldHdvcmtfaWReBdYRCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:deepslate_emerald_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSWAgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV9lbWVyYWxkX29yZQQJAG5hbWVfaGFzaNlfo5HTwS6wAwoAbmV0d29ya19pZNeie6sKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:deepslate_coal_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSVAgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9jb2FsX29yZQQJAG5hbWVfaGFzaIjikmcbRrPPAwoAbmV0d29ya19pZD9TiygKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:deepslate_copper_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSXAgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9jb3BwZXJfb3JlBAkAbmFtZV9oYXNottjV4Ev5LAQDCgBuZXR3b3JrX2lkP23rgQoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:gravel", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQNAAAACAQAbmFtZRAAbWluZWNyYWZ0OmdyYXZlbAQJAG5hbWVfaGFzaOFxz8XJd2r/AwoAbmV0d29ya19pZBpfI1sKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:granite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRNAwAACAQAbmFtZREAbWluZWNyYWZ0OmdyYW5pdGUECQBuYW1lX2hhc2iq+Dur2pw4AwMKAG5ldHdvcmtfaWT2NMfJCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:diorite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRPAwAACAQAbmFtZREAbWluZWNyYWZ0OmRpb3JpdGUECQBuYW1lX2hhc2iaFsq2iinZBQMKAG5ldHdvcmtfaWQqGE6XCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:andesite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRRAwAACAQAbmFtZRIAbWluZWNyYWZ0OmFuZGVzaXRlBAkAbmFtZV9oYXNosaLIEnQQoSYDCgBuZXR3b3JrX2lkEApRZAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:blackstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQQAgAACAQAbmFtZRQAbWluZWNyYWZ0OmJsYWNrc3RvbmUECQBuYW1lX2hhc2iMFYziD80D6QMKAG5ldHdvcmtfaWSrUryHCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR5AgAACAQAbmFtZRMAbWluZWNyYWZ0OmRlZXBzbGF0ZQQJAG5hbWVfaGFzaKX5pAblxz8TAwoAbmV0d29ya19pZOJoQjsKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:polished_granite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWROAwAACAQAbmFtZRoAbWluZWNyYWZ0OnBvbGlzaGVkX2dyYW5pdGUECQBuYW1lX2hhc2iLiEfys8pFIAMKAG5ldHdvcmtfaWTCxxcHCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:polished_diorite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRQAwAACAQAbmFtZRoAbWluZWNyYWZ0OnBvbGlzaGVkX2Rpb3JpdGUECQBuYW1lX2hhc2hTxY4fKmNmlAMKAG5ldHdvcmtfaWTmtjdRCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:polished_andesite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRSAwAACAQAbmFtZRsAbWluZWNyYWZ0OnBvbGlzaGVkX2FuZGVzaXRlBAkAbmFtZV9oYXNovl28uFk4HuQDCgBuZXR3b3JrX2lklFjuCwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:polished_blackstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQiAgAACAQAbmFtZR0AbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmUECQBuYW1lX2hhc2jT9fHCl6vWQQMKAG5ldHdvcmtfaWR/Ho6oCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:polished_deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR+AgAACAQAbmFtZRwAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaHC1edoaWF3uAwoAbmV0d29ya19pZCPeQsEKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:sand", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQMAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnNhbmQECQBuYW1lX2hhc2i6lthXXbAyWAMKAG5ldHdvcmtfaWRjeUMICgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:red_sand", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS0BAAACAQAbmFtZRIAbWluZWNyYWZ0OnJlZF9zYW5kBAkAbmFtZV9oYXNoCiarI69JQCkDCgBuZXR3b3JrX2lkU8UD/AoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:cactus", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRRAAAACAQAbmFtZRAAbWluZWNyYWZ0OmNhY3R1cwQJAG5hbWVfaGFzaCG9zL0N4wvGAwoAbmV0d29ya19pZDeCERAKBgBzdGF0ZXMDAwBhZ2UAAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:oak_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQRAAAACAQAbmFtZREAbWluZWNyYWZ0Om9ha19sb2cECQBuYW1lX2hhc2ho6TS+K7PZFQMKAG5ldHdvcmtfaWQjfjoxCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:stripped_oak_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQJAQAACAQAbmFtZRoAbWluZWNyYWZ0OnN0cmlwcGVkX29ha19sb2cECQBuYW1lX2hhc2h8dqh+OOHU4wMKAG5ldHdvcmtfaWSYKjdrCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:spruce_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ4AwAACAQAbmFtZRQAbWluZWNyYWZ0OnNwcnVjZV9sb2cECQBuYW1lX2hhc2hZ03qaLoF3WgMKAG5ldHdvcmtfaWRlFD8eCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:stripped_spruce_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQEAQAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX3NwcnVjZV9sb2cECQBuYW1lX2hhc2iNrhKjS5IyrgMKAG5ldHdvcmtfaWRQcEC3CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:birch_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ5AwAACAQAbmFtZRMAbWluZWNyYWZ0OmJpcmNoX2xvZwQJAG5hbWVfaGFzaBUzT3NxsZAnAwoAbmV0d29ya19pZBKN3VQKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:stripped_birch_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQFAQAACAQAbmFtZRwAbWluZWNyYWZ0OnN0cmlwcGVkX2JpcmNoX2xvZwQJAG5hbWVfaGFzaCFKS4AeuSidAwoAbmV0d29ya19pZN0IONIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:jungle_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ6AwAACAQAbmFtZRQAbWluZWNyYWZ0Omp1bmdsZV9sb2cECQBuYW1lX2hhc2gkwW0KNulqDgMKAG5ldHdvcmtfaWQaziU/CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:stripped_jungle_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAQAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2p1bmdsZV9sb2cECQBuYW1lX2hhc2hAwMsgOk02JAMKAG5ldHdvcmtfaWQvls0eCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:acacia_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAAAACAQAbmFtZRQAbWluZWNyYWZ0OmFjYWNpYV9sb2cECQBuYW1lX2hhc2iV48VpYhjoYQMKAG5ldHdvcmtfaWRxEqe0CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:stripped_acacia_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAQAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2FjYWNpYV9sb2cECQBuYW1lX2hhc2hJb0lQqnEqlgMKAG5ldHdvcmtfaWRg3IdRCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:dark_oak_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ7AwAACAQAbmFtZRYAbWluZWNyYWZ0OmRhcmtfb2FrX2xvZwQJAG5hbWVfaGFzaIWfVRd0XUo3AwoAbmV0d29ya19pZPMM7LYKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:stripped_dark_oak_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQIAQAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2Rhcmtfb2FrX2xvZwQJAG5hbWVfaGFzaPFTdxRdPwkOAwoAbmV0d29ya19pZDIzenIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:mangrove_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAgAACAQAbmFtZRYAbWluZWNyYWZ0Om1hbmdyb3ZlX2xvZwQJAG5hbWVfaGFzaHZe6DzPZBobAwoAbmV0d29ya19pZG6DuYkKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:stripped_mangrove_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX21hbmdyb3ZlX2xvZwQJAG5hbWVfaGFzaLqIBo4hwA//AwoAbmV0d29ya19pZPtRn7UKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:cherry_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQXAwAACAQAbmFtZRQAbWluZWNyYWZ0OmNoZXJyeV9sb2cECQBuYW1lX2hhc2hwFlaioppB1wMKAG5ldHdvcmtfaWS2sdXECgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:stripped_cherry_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQWAwAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2NoZXJyeV9sb2cECQBuYW1lX2hhc2i85H6G+WhXaAMKAG5ldHdvcmtfaWRjzoglCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:crimson_stem", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAQAACAQAbmFtZRYAbWluZWNyYWZ0OmNyaW1zb25fc3RlbQQJAG5hbWVfaGFzaM0FzfL0UTKZAwoAbmV0d29ya19pZKvzID0KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:stripped_crimson_stem", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTvAQAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2NyaW1zb25fc3RlbQQJAG5hbWVfaGFzaDlA6nood57EAwoAbmV0d29ya19pZHrIqjIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:warped_stem", + "block_state_b64": "CgAAAwgAYmxvY2tfaWThAQAACAQAbmFtZRUAbWluZWNyYWZ0OndhcnBlZF9zdGVtBAkAbmFtZV9oYXNon7cKfPZxdrUDCgBuZXR3b3JrX2lkerWyMwoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:stripped_warped_stem", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTwAQAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX3dhcnBlZF9zdGVtBAkAbmFtZV9oYXNoEw+y0dDPSd8DCgBuZXR3b3JrX2lkIQ9vBAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:oak_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAQAACAQAbmFtZRIAbWluZWNyYWZ0Om9ha193b29kBAkAbmFtZV9oYXNoqQIkuVPyJX0DCgBuZXR3b3JrX2lku2G1YAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:spruce_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQtBAAACAQAbmFtZRUAbWluZWNyYWZ0OnNwcnVjZV93b29kBAkAbmFtZV9oYXNoTrIJ5TAQ+OgDCgBuZXR3b3JrX2lkaXLxCwoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:birch_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQuBAAACAQAbmFtZRQAbWluZWNyYWZ0OmJpcmNoX3dvb2QECQBuYW1lX2hhc2iqVjG4xt0cKQMKAG5ldHdvcmtfaWS06c5VCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:jungle_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQvBAAACAQAbmFtZRUAbWluZWNyYWZ0Omp1bmdsZV93b29kBAkAbmFtZV9oYXNo9bYW29ORWCoDCgBuZXR3b3JrX2lkyFyKLQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:acacia_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQwBAAACAQAbmFtZRUAbWluZWNyYWZ0OmFjYWNpYV93b29kBAkAbmFtZV9oYXNoKkDfgzlJUcIDCgBuZXR3b3JrX2lkuTWlcgoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:dark_oak_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQxBAAACAQAbmFtZRcAbWluZWNyYWZ0OmRhcmtfb2FrX3dvb2QECQBuYW1lX2hhc2jaKv4ORLadAAMKAG5ldHdvcmtfaWSDrNQ8CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:stripped_oak_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQyBAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0cmlwcGVkX29ha193b29kBAkAbmFtZV9oYXNovW6KCv+VZnsDCgBuZXR3b3JrX2lkkhWGegoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:stripped_spruce_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQzBAAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX3NwcnVjZV93b29kBAkAbmFtZV9oYXNoMnuUk4Xo6icDCgBuZXR3b3JrX2lkes2ydAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:stripped_birch_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ0BAAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2JpcmNoX3dvb2QECQBuYW1lX2hhc2hm88R604TKbAMKAG5ldHdvcmtfaWRleEMJCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:stripped_jungle_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ1BAAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX2p1bmdsZV93b29kBAkAbmFtZV9oYXNoUVs6KsZQRBoDCgBuZXR3b3JrX2lk92k8HQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:stripped_acacia_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ2BAAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX2FjYWNpYV93b29kBAkAbmFtZV9oYXNo/kOPN2bCJhUDCgBuZXR3b3JrX2lktl6LwQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:stripped_dark_oak_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ3BAAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX2Rhcmtfb2FrX3dvb2QECQBuYW1lX2hhc2h2jFDfKVFgfAMKAG5ldHdvcmtfaWTgZQ5VCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:mangrove_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTwAgAACAQAbmFtZRcAbWluZWNyYWZ0Om1hbmdyb3ZlX3dvb2QECQBuYW1lX2hhc2iXVxG0JG2fVAMKAG5ldHdvcmtfaWTok1JCCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:stripped_mangrove_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTxAgAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX21hbmdyb3ZlX3dvb2QECQBuYW1lX2hhc2h7CkbaBF7/WAMKAG5ldHdvcmtfaWQLAX88CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:cherry_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQhAwAACAQAbmFtZRUAbWluZWNyYWZ0OmNoZXJyeV93b29kBAkAbmFtZV9oYXNoAW8srlmpBM8DCgBuZXR3b3JrX2lkEALMfAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AQwAc3RyaXBwZWRfYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:stripped_cherry_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQgAwAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX2NoZXJyeV93b29kBAkAbmFtZV9oYXNo/e7KXv+CB38DCgBuZXR3b3JrX2lkg5aVtQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:crimson_hyphae", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQqAgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25faHlwaGFlBAkAbmFtZV9oYXNouRmKmfSqEWADCgBuZXR3b3JrX2lk+Tm5rQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:stripped_crimson_hyphae", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQrAgAACAQAbmFtZSEAbWluZWNyYWZ0OnN0cmlwcGVkX2NyaW1zb25faHlwaGFlBAkAbmFtZV9oYXNoFffwmABq4LUDCgBuZXR3b3JrX2lkZAlUbgoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:warped_hyphae", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQpAgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9oeXBoYWUECQBuYW1lX2hhc2hn8plQUr6pmQMKAG5ldHdvcmtfaWRU2AIBCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:stripped_warped_hyphae", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAgAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX3dhcnBlZF9oeXBoYWUECQBuYW1lX2hhc2irKq+HYPSgjQMKAG5ldHdvcmtfaWSbrOPDCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:bamboo_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQOAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJhbWJvb19ibG9jawQJAG5hbWVfaGFzaAbDeur6stIBAwoAbmV0d29ya19pZCJAwn0KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:stripped_bamboo_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQPAwAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2JhbWJvb19ibG9jawQJAG5hbWVfaGFzaJpwytpZOZM9AwoAbmV0d29ya19pZKuRbNEKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:oak_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQSAAAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19sZWF2ZXMECQBuYW1lX2hhc2h6O4xGqA2oKgMKAG5ldHdvcmtfaWT98c59CgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:spruce_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQfBAAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9sZWF2ZXMECQBuYW1lX2hhc2i9x1CtNAuqZwMKAG5ldHdvcmtfaWSzF7pTCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:birch_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQgBAAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX2xlYXZlcwQJAG5hbWVfaGFzaBlAGHaoaLZSAwoAbmV0d29ya19pZOjtvWcKBgBzdGF0ZXMBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:jungle_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQhBAAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9sZWF2ZXMECQBuYW1lX2hhc2iW1uAH07zGhgMKAG5ldHdvcmtfaWSA5KX0CgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:acacia_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAAAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9sZWF2ZXMECQBuYW1lX2hhc2iZJf8dAgDRNQMKAG5ldHdvcmtfaWQ/G7VuCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:dark_oak_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQiBAAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX2xlYXZlcwQJAG5hbWVfaGFzaCk7rDipWFSjAwoAbmV0d29ya19pZJ2AkbYKBgBzdGF0ZXMBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:mangrove_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX2xlYXZlcwQJAG5hbWVfaGFzaKyI/dWvhEG8AwoAbmV0d29ya19pZPQxCZ8KBgBzdGF0ZXMBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:cherry_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQjAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9sZWF2ZXMECQBuYW1lX2hhc2giTs9ChhYBlQMKAG5ldHdvcmtfaWR8bPpwCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:azalea_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRDAgAACAQAbmFtZRcAbWluZWNyYWZ0OmF6YWxlYV9sZWF2ZXMECQBuYW1lX2hhc2iXFhD57wFS7AMKAG5ldHdvcmtfaWTNB/9ECgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:azalea_leaves_flowered", + "block_state_b64": "CgAAAwgAYmxvY2tfaWREAgAACAQAbmFtZSAAbWluZWNyYWZ0OmF6YWxlYV9sZWF2ZXNfZmxvd2VyZWQECQBuYW1lX2hhc2gs8jxlS/pMrwMKAG5ldHdvcmtfaWQ7W4PyCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:oak_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAAAACAQAbmFtZRUAbWluZWNyYWZ0Om9ha19zYXBsaW5nBAkAbmFtZV9oYXNoogXcT9QfjiUDCgBuZXR3b3JrX2lkG22C+AoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:spruce_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ4BAAACAQAbmFtZRgAbWluZWNyYWZ0OnNwcnVjZV9zYXBsaW5nBAkAbmFtZV9oYXNoe8hz4uYP0FcDCgBuZXR3b3JrX2lkUQmhaQoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:birch_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ5BAAACAQAbmFtZRcAbWluZWNyYWZ0OmJpcmNoX3NhcGxpbmcECQBuYW1lX2hhc2h348iJQ/tK4wMKAG5ldHdvcmtfaWQ2Uh53CgYAc3RhdGVzAQcAYWdlX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:jungle_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ6BAAACAQAbmFtZRgAbWluZWNyYWZ0Omp1bmdsZV9zYXBsaW5nBAkAbmFtZV9oYXNo7tyTOdSrxaADCgBuZXR3b3JrX2lkXmBAdAoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:acacia_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ7BAAACAQAbmFtZRgAbWluZWNyYWZ0OmFjYWNpYV9zYXBsaW5nBAkAbmFtZV9oYXNo99sg15uoX7ADCgBuZXR3b3JrX2lkPXX1KgoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:dark_oak_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ8BAAACAQAbmFtZRoAbWluZWNyYWZ0OmRhcmtfb2FrX3NhcGxpbmcECQBuYW1lX2hhc2jnVzFplW7cHgMKAG5ldHdvcmtfaWTD4giHCgYAc3RhdGVzAQcAYWdlX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:mangrove_propagule", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTZAgAACAQAbmFtZRwAbWluZWNyYWZ0Om1hbmdyb3ZlX3Byb3BhZ3VsZQQJAG5hbWVfaGFzaJGeox6hkfLFAwoAbmV0d29ya19pZAIpvpYKBgBzdGF0ZXMBBwBoYW5naW5nAAMPAHByb3BhZ3VsZV9zdGFnZQAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:cherry_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQiAwAACAQAbmFtZRgAbWluZWNyYWZ0OmNoZXJyeV9zYXBsaW5nBAkAbmFtZV9oYXNoGrPpNMf1LtcDCgBuZXR3b3JrX2lkypakXQoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:bee_nest", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTZAQAACAQAbmFtZRIAbWluZWNyYWZ0OmJlZV9uZXN0BAkAbmFtZV9oYXNo2R2WBxUHEZIDCgBuZXR3b3JrX2lkiXWLEAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAADCwBob25leV9sZXZlbAAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "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": "CgAAAwgAYmxvY2tfaWRnAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1lbG9uX2Jsb2NrBAkAbmFtZV9oYXNoXxSm0iYpAx8DCgBuZXR3b3JrX2lkC9rqygoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:melon_slice" + }, + { + "id": "minecraft:glistering_melon_slice" + }, + { + "id": "minecraft:sweet_berries" + }, + { + "id": "minecraft:glow_berries" + }, + { + "id": "minecraft:pumpkin", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRWAAAACAQAbmFtZREAbWluZWNyYWZ0OnB1bXBraW4ECQBuYW1lX2hhc2gc8A3jaSzWbgMKAG5ldHdvcmtfaWRFGA+xCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:carved_pumpkin", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSaAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNhcnZlZF9wdW1wa2luBAkAbmFtZV9oYXNoPu1T0MJuG90DCgBuZXR3b3JrX2lkXNNn5QoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:lit_pumpkin", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRbAAAACAQAbmFtZRUAbWluZWNyYWZ0OmxpdF9wdW1wa2luBAkAbmFtZV9oYXNo7gWtEm2uPL0DCgBuZXR3b3JrX2lki8sU4AoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:honeycomb" + }, + { + "id": "minecraft:fern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRPBAAACAQAbmFtZQ4AbWluZWNyYWZ0OmZlcm4ECQBuYW1lX2hhc2iHbj3yXFn4owMKAG5ldHdvcmtfaWQKC6u7CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:large_fern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRgBAAACAQAbmFtZRQAbWluZWNyYWZ0OmxhcmdlX2Zlcm4ECQBuYW1lX2hhc2gnE9sd0LzHtQMKAG5ldHdvcmtfaWTS9hG4CgYAc3RhdGVzAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:short_grass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQfAAAACAQAbmFtZRUAbWluZWNyYWZ0OnNob3J0X2dyYXNzBAkAbmFtZV9oYXNobWQghLH0bLcDCgBuZXR3b3JrX2lkJWOOqAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:tall_grass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRfBAAACAQAbmFtZRQAbWluZWNyYWZ0OnRhbGxfZ3Jhc3MECQBuYW1lX2hhc2ii5MyZJpv4sgMKAG5ldHdvcmtfaWRRfeH4CgYAc3RhdGVzAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:nether_sprouts" + }, + { + "id": "minecraft:fire_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRGAwAACAQAbmFtZRQAbWluZWNyYWZ0OmZpcmVfY29yYWwECQBuYW1lX2hhc2hOHyyECVQVJwMKAG5ldHdvcmtfaWS9vF0UCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:brain_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWREAwAACAQAbmFtZRUAbWluZWNyYWZ0OmJyYWluX2NvcmFsBAkAbmFtZV9oYXNoRiWlLCwA2ycDCgBuZXR3b3JrX2lkrjAuhgoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:bubble_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRFAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJ1YmJsZV9jb3JhbAQJAG5hbWVfaGFzaJz6rWnl+v2qAwoAbmV0d29ya19pZImIWy0KBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:tube_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAQAACAQAbmFtZRQAbWluZWNyYWZ0OnR1YmVfY29yYWwECQBuYW1lX2hhc2iYa8oO/tgk7wMKAG5ldHdvcmtfaWRTfND5CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:horn_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRHAwAACAQAbmFtZRQAbWluZWNyYWZ0Omhvcm5fY29yYWwECQBuYW1lX2hhc2iZnRHjZbnLPgMKAG5ldHdvcmtfaWR+GGp8CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:dead_fire_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRLAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfZmlyZV9jb3JhbAQJAG5hbWVfaGFzaEPU6tFy/latAwoAbmV0d29ya19pZNMa7V4KBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:dead_brain_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRJAwAACAQAbmFtZRoAbWluZWNyYWZ0OmRlYWRfYnJhaW5fY29yYWwECQBuYW1lX2hhc2j5L6QJCISvzwMKAG5ldHdvcmtfaWQkKzeiCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:dead_bubble_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRKAwAACAQAbmFtZRsAbWluZWNyYWZ0OmRlYWRfYnViYmxlX2NvcmFsBAkAbmFtZV9oYXNoSTOZ/8wpeNYDCgBuZXR3b3JrX2lka6w9DAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:dead_tube_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRIAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfdHViZV9jb3JhbAQJAG5hbWVfaGFzaJGjNWhlaIJeAwoAbmV0d29ya19pZO3Z0ygKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:dead_horn_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRMAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfaG9ybl9jb3JhbAQJAG5hbWVfaGFzaJBkz3qt+g2cAwoAbmV0d29ya19pZBAN+eYKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:fire_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRJBAAACAQAbmFtZRgAbWluZWNyYWZ0OmZpcmVfY29yYWxfZmFuBAkAbmFtZV9oYXNosOTxYYxsDLgDCgBuZXR3b3JrX2lkFKxbEgoGAHN0YXRlcwMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:brain_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRHBAAACAQAbmFtZRkAbWluZWNyYWZ0OmJyYWluX2NvcmFsX2ZhbgQJAG5hbWVfaGFzaAi5uHizSNcqAwoAbmV0d29ya19pZFtLjNwKBgBzdGF0ZXMDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:bubble_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRIBAAACAQAbmFtZRoAbWluZWNyYWZ0OmJ1YmJsZV9jb3JhbF9mYW4ECQBuYW1lX2hhc2hy/rX2on17DgMKAG5ldHdvcmtfaWQof60VCgYAc3RhdGVzAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:tube_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAQAACAQAbmFtZRgAbWluZWNyYWZ0OnR1YmVfY29yYWxfZmFuBAkAbmFtZV9oYXNo9pbJbo+PphIDCgBuZXR3b3JrX2lkenDTYgoGAHN0YXRlcwMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:horn_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRKBAAACAQAbmFtZRgAbWluZWNyYWZ0Omhvcm5fY29yYWxfZmFuBAkAbmFtZV9oYXNoA+ri6NPDkbUDCgBuZXR3b3JrX2lkezoHNwoGAHN0YXRlcwMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:dead_fire_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRNBAAACAQAbmFtZR0AbWluZWNyYWZ0OmRlYWRfZmlyZV9jb3JhbF9mYW4ECQBuYW1lX2hhc2hpQO02NDxPvwMKAG5ldHdvcmtfaWTaOJgLCgYAc3RhdGVzAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:dead_brain_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRLBAAACAQAbmFtZR4AbWluZWNyYWZ0OmRlYWRfYnJhaW5fY29yYWxfZmFuBAkAbmFtZV9oYXNoI9/+Z4YqMhIDCgBuZXR3b3JrX2lkqYXxYgoGAHN0YXRlcwMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:dead_bubble_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRMBAAACAQAbmFtZR8AbWluZWNyYWZ0OmRlYWRfYnViYmxlX2NvcmFsX2ZhbgQJAG5hbWVfaGFzaBNECtIM6VIOAwoAbmV0d29ya19pZLrNtBEKBgBzdGF0ZXMDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:dead_tube_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAQAACAQAbmFtZR0AbWluZWNyYWZ0OmRlYWRfdHViZV9jb3JhbF9mYW4ECQBuYW1lX2hhc2hbBBM9jFKWvQMKAG5ldHdvcmtfaWSkJKUWCgYAc3RhdGVzAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:dead_horn_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWROBAAACAQAbmFtZR0AbWluZWNyYWZ0OmRlYWRfaG9ybl9jb3JhbF9mYW4ECQBuYW1lX2hhc2hObElFrHfPygMKAG5ldHdvcmtfaWQ1ZxvmCgYAc3RhdGVzAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:crimson_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTeAQAACAQAbmFtZRcAbWluZWNyYWZ0OmNyaW1zb25fcm9vdHMECQBuYW1lX2hhc2j1fWgQLViv5QMKAG5ldHdvcmtfaWRLh5DXCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:warped_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAQAACAQAbmFtZRYAbWluZWNyYWZ0OndhcnBlZF9yb290cwQJAG5hbWVfaGFzaBc3WvbJOLlkAwoAbmV0d29ya19pZNLgDnAKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:dandelion", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQlAAAACAQAbmFtZRMAbWluZWNyYWZ0OmRhbmRlbGlvbgQJAG5hbWVfaGFzaBJ3bEUi+Nn/AwoAbmV0d29ya19pZBjjC44KBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:poppy", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZQ8AbWluZWNyYWZ0OnBvcHB5BAkAbmFtZV9oYXNocMF8pITMbkcDCgBuZXR3b3JrX2lk8im6ywoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:blue_orchid", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ9BAAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfb3JjaGlkBAkAbmFtZV9oYXNoBjz2MsgB21EDCgBuZXR3b3JrX2lk/iLsSwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:allium", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ+BAAACAQAbmFtZRAAbWluZWNyYWZ0OmFsbGl1bQQJAG5hbWVfaGFzaDCGQBHNDTkcAwoAbmV0d29ya19pZD9Dgr0KBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:azure_bluet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ/BAAACAQAbmFtZRUAbWluZWNyYWZ0OmF6dXJlX2JsdWV0BAkAbmFtZV9oYXNo9N5egqMT2QcDCgBuZXR3b3JrX2lkwIgDnwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:red_tulip", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRABAAACAQAbmFtZRMAbWluZWNyYWZ0OnJlZF90dWxpcAQJAG5hbWVfaGFzaAjMi9Rd+6rhAwoAbmV0d29ya19pZAZCnt8KBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:orange_tulip", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRBBAAACAQAbmFtZRYAbWluZWNyYWZ0Om9yYW5nZV90dWxpcAQJAG5hbWVfaGFzaP+NjxMBZ8vAAwoAbmV0d29ya19pZPYatsMKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:white_tulip", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRCBAAACAQAbmFtZRUAbWluZWNyYWZ0OndoaXRlX3R1bGlwBAkAbmFtZV9oYXNo5vbU4VRPh3ADCgBuZXR3b3JrX2lkok+4rQoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:pink_tulip", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRDBAAACAQAbmFtZRQAbWluZWNyYWZ0OnBpbmtfdHVsaXAECQBuYW1lX2hhc2hxDHZa6OaNXAMKAG5ldHdvcmtfaWTiOT+VCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:oxeye_daisy", + "block_state_b64": "CgAAAwgAYmxvY2tfaWREBAAACAQAbmFtZRUAbWluZWNyYWZ0Om94ZXllX2RhaXN5BAkAbmFtZV9oYXNoXwxsqNQTN9gDCgBuZXR3b3JrX2lkw7R7dwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:cornflower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRFBAAACAQAbmFtZRQAbWluZWNyYWZ0OmNvcm5mbG93ZXIECQBuYW1lX2hhc2gnhyC3EeqHgAMKAG5ldHdvcmtfaWR4VrvACgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:lily_of_the_valley", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRGBAAACAQAbmFtZRwAbWluZWNyYWZ0OmxpbHlfb2ZfdGhlX3ZhbGxleQQJAG5hbWVfaGFzaI64TJSf9mgQAwoAbmV0d29ya19pZFE9+nwKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:sunflower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRMAbWluZWNyYWZ0OnN1bmZsb3dlcgQJAG5hbWVfaGFzaAMxYQLoqlZ0AwoAbmV0d29ya19pZA10iSoKBgBzdGF0ZXMBDwB1cHBlcl9ibG9ja19iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:lilac", + "block_state_b64": "CgAAAwgAYmxvY2tfaWReBAAACAQAbmFtZQ8AbWluZWNyYWZ0OmxpbGFjBAkAbmFtZV9oYXNoD3nrQJuo7NkDCgBuZXR3b3JrX2lk5W+uFAoGAHN0YXRlcwEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:rose_bush", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhBAAACAQAbmFtZRMAbWluZWNyYWZ0OnJvc2VfYnVzaAQJAG5hbWVfaGFzaLoiFk8LVpGKAwoAbmV0d29ya19pZMZPv48KBgBzdGF0ZXMBDwB1cHBlcl9ibG9ja19iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:peony", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiBAAACAQAbmFtZQ8AbWluZWNyYWZ0OnBlb255BAkAbmFtZV9oYXNoR4dYc4QquPADCgBuZXR3b3JrX2lkrTe7RwoGAHN0YXRlcwEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:pitcher_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAwAACAQAbmFtZRcAbWluZWNyYWZ0OnBpdGNoZXJfcGxhbnQECQBuYW1lX2hhc2hRJHzsbDH+SQMKAG5ldHdvcmtfaWRnY76VCgYAc3RhdGVzAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:pink_petals", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQkAwAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfcGV0YWxzBAkAbmFtZV9oYXNo6DQwN9SwV3QDCgBuZXR3b3JrX2lkNWneGgoGAHN0YXRlcwMGAGdyb3d0aAAAAAAIHABtaW5lY3JhZnQ6Y2FyZGluYWxfZGlyZWN0aW9uBQBzb3V0aAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:wither_rose", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAQAACAQAbmFtZRUAbWluZWNyYWZ0OndpdGhlcl9yb3NlBAkAbmFtZV9oYXNoaSKxl3I516gDCgBuZXR3b3JrX2lkATXLPwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:torchflower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ3AwAACAQAbmFtZRUAbWluZWNyYWZ0OnRvcmNoZmxvd2VyBAkAbmFtZV9oYXNoL+mHtElwbqQDCgBuZXR3b3JrX2lkI34O+AoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "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/XeXOLAMKAG5ldHdvcmtfaWSUkDtbCgYAc3RhdGVzAxMAdmluZV9kaXJlY3Rpb25fYml0cwAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:weeping_vines", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTmAQAACAQAbmFtZRcAbWluZWNyYWZ0OndlZXBpbmdfdmluZXMECQBuYW1lX2hhc2jrLgLHkQygiwMKAG5ldHdvcmtfaWQ8NHSJCgYAc3RhdGVzAxEAd2VlcGluZ192aW5lc19hZ2UAAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:twisting_vines", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQeAgAACAQAbmFtZRgAbWluZWNyYWZ0OnR3aXN0aW5nX3ZpbmVzBAkAbmFtZV9oYXNoDYR5QgVUQJADCgBuZXR3b3JrX2lk5kYVIQoGAHN0YXRlcwMSAHR3aXN0aW5nX3ZpbmVzX2FnZQAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:waterlily", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRvAAAACAQAbmFtZRMAbWluZWNyYWZ0OndhdGVybGlseQQJAG5hbWVfaGFzaEHgC4c1SXg0AwoAbmV0d29ya19pZOOerp8KBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:seagrass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAQAACAQAbmFtZRIAbWluZWNyYWZ0OnNlYWdyYXNzBAkAbmFtZV9oYXNoHSBFtoHdWxIDCgBuZXR3b3JrX2lkd3lhEAoGAHN0YXRlcwgOAHNlYV9ncmFzc190eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:kelp" + }, + { + "id": "minecraft:deadbush", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQgAAAACAQAbmFtZRIAbWluZWNyYWZ0OmRlYWRidXNoBAkAbmFtZV9oYXNoPFODe4IScnYDCgBuZXR3b3JrX2lkVfnl+goGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:bamboo", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAQAACAQAbmFtZRAAbWluZWNyYWZ0OmJhbWJvbwQJAG5hbWVfaGFzaBgpGmyzhedCAwoAbmV0d29ya19pZIZv1nYKBgBzdGF0ZXMBBwBhZ2VfYml0AAgQAGJhbWJvb19sZWFmX3NpemUJAG5vX2xlYXZlcwgWAGJhbWJvb19zdGFsa190aGlja25lc3MEAHRoaW4AAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:snow", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRQAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnNub3cECQBuYW1lX2hhc2gVHr5XXdETWAMKAG5ldHdvcmtfaWQ0zCeHCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:ice", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRPAAAACAQAbmFtZQ0AbWluZWNyYWZ0OmljZQQJAG5hbWVfaGFzaNF26f+uUT29AwoAbmV0d29ya19pZOUMaQYKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:packed_ice", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSuAAAACAQAbmFtZRQAbWluZWNyYWZ0OnBhY2tlZF9pY2UECQBuYW1lX2hhc2hk4bu123ZrFgMKAG5ldHdvcmtfaWTr/ooaCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:blue_ice", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQKAQAACAQAbmFtZRIAbWluZWNyYWZ0OmJsdWVfaWNlBAkAbmFtZV9oYXNo+EKxYgFhKcgDCgBuZXR3b3JrX2lkxfsA8goGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:snow_layer", + "block_state_b64": "CgAAAwgAYmxvY2tfaWROAAAACAQAbmFtZRQAbWluZWNyYWZ0OnNub3dfbGF5ZXIECQBuYW1lX2hhc2hXka6atMYUCQMKAG5ldHdvcmtfaWRCrIPcCgYAc3RhdGVzAQsAY292ZXJlZF9iaXQAAwYAaGVpZ2h0AAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:pointed_dripstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQzAgAACAQAbmFtZRsAbWluZWNyYWZ0OnBvaW50ZWRfZHJpcHN0b25lBAkAbmFtZV9oYXNoJMISzmHQgt8DCgBuZXR3b3JrX2lkbWrtYgoGAHN0YXRlcwgTAGRyaXBzdG9uZV90aGlja25lc3MDAHRpcAEHAGhhbmdpbmcBAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:dripstone_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ8AgAACAQAbmFtZRkAbWluZWNyYWZ0OmRyaXBzdG9uZV9ibG9jawQJAG5hbWVfaGFzaIIXnEqY77YsAwoAbmV0d29ya19pZMZi2kwKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:moss_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWROAgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vc3NfY2FycGV0BAkAbmFtZV9oYXNo/NEDxRPTshYDCgBuZXR3b3JrX2lkaGG3QwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:moss_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ/AgAACAQAbmFtZRQAbWluZWNyYWZ0Om1vc3NfYmxvY2sECQBuYW1lX2hhc2iovcsPUYX2tgMKAG5ldHdvcmtfaWT3JSbfCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:dirt_with_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ9AgAACAQAbmFtZRkAbWluZWNyYWZ0OmRpcnRfd2l0aF9yb290cwQJAG5hbWVfaGFzaLCNDYPviDCIAwoAbmV0d29ya19pZNCkwzoKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:hanging_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ+AgAACAQAbmFtZRcAbWluZWNyYWZ0Omhhbmdpbmdfcm9vdHMECQBuYW1lX2hhc2jaXn+Y5UZpDAMKAG5ldHdvcmtfaWRU4c2vCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:mangrove_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWThAgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hbmdyb3ZlX3Jvb3RzBAkAbmFtZV9oYXNoa786PzQGZ6kDCgBuZXR3b3JrX2lklA0AHgoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:muddy_mangrove_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAgAACAQAbmFtZR4AbWluZWNyYWZ0Om11ZGR5X21hbmdyb3ZlX3Jvb3RzBAkAbmFtZV9oYXNo9YApdHpo1RkDCgBuZXR3b3JrX2lkH0Oc4woGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:big_dripleaf", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRCAgAACAQAbmFtZRYAbWluZWNyYWZ0OmJpZ19kcmlwbGVhZgQJAG5hbWVfaGFzaGBEhXjo6qSdAwoAbmV0d29ya19pZMETsb8KBgBzdGF0ZXMBEQBiaWdfZHJpcGxlYWZfaGVhZAEIEQBiaWdfZHJpcGxlYWZfdGlsdAQAbm9uZQgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:small_dripleaf_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRPAgAACAQAbmFtZR4AbWluZWNyYWZ0OnNtYWxsX2RyaXBsZWFmX2Jsb2NrBAkAbmFtZV9oYXNojxRAgXP9uWADCgBuZXR3b3JrX2lkozbVPwoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24EAGVhc3QBDwB1cHBlcl9ibG9ja19iaXQBAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:spore_blossom", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRAAgAACAQAbmFtZRcAbWluZWNyYWZ0OnNwb3JlX2Jsb3Nzb20ECQBuYW1lX2hhc2il3U72Gbco2gMKAG5ldHdvcmtfaWSbbbgcCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:azalea", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRQAgAACAQAbmFtZRAAbWluZWNyYWZ0OmF6YWxlYQQJAG5hbWVfaGFzaNyUl+BW9JrBAwoAbmV0d29ya19pZO/XZtQKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:flowering_azalea", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRRAgAACAQAbmFtZRoAbWluZWNyYWZ0OmZsb3dlcmluZ19hemFsZWEECQBuYW1lX2hhc2ie9r33wz8kiwMKAG5ldHdvcmtfaWQ3ij0VCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:glow_lichen", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSaAgAACAQAbmFtZRUAbWluZWNyYWZ0Omdsb3dfbGljaGVuBAkAbmFtZV9oYXNobyPUrIYlo44DCgBuZXR3b3JrX2lkCh8lSAoGAHN0YXRlcwMZAG11bHRpX2ZhY2VfZGlyZWN0aW9uX2JpdHM/AAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:amethyst_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRGAgAACAQAbmFtZRgAbWluZWNyYWZ0OmFtZXRoeXN0X2Jsb2NrBAkAbmFtZV9oYXNob+JK1iiAthcDCgBuZXR3b3JrX2lk8HtpzgoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:budding_amethyst", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRHAgAACAQAbmFtZRoAbWluZWNyYWZ0OmJ1ZGRpbmdfYW1ldGh5c3QECQBuYW1lX2hhc2gJvAwfI14fxgMKAG5ldHdvcmtfaWTQYqfACgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:amethyst_cluster", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRIAgAACAQAbmFtZRoAbWluZWNyYWZ0OmFtZXRoeXN0X2NsdXN0ZXIECQBuYW1lX2hhc2jK82S88Jgm8wMKAG5ldHdvcmtfaWSCPMPGCgYAc3RhdGVzCBQAbWluZWNyYWZ0OmJsb2NrX2ZhY2UCAHVwAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:large_amethyst_bud", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRJAgAACAQAbmFtZRwAbWluZWNyYWZ0OmxhcmdlX2FtZXRoeXN0X2J1ZAQJAG5hbWVfaGFzaAHhdpWD+sd5AwoAbmV0d29ya19pZKkQxOcKBgBzdGF0ZXMIFABtaW5lY3JhZnQ6YmxvY2tfZmFjZQIAdXAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:medium_amethyst_bud", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRKAgAACAQAbmFtZR0AbWluZWNyYWZ0Om1lZGl1bV9hbWV0aHlzdF9idWQECQBuYW1lX2hhc2g5lBGtC0DzZQMKAG5ldHdvcmtfaWSYiP4gCgYAc3RhdGVzCBQAbWluZWNyYWZ0OmJsb2NrX2ZhY2UCAHVwAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:small_amethyst_bud", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRLAgAACAQAbmFtZRwAbWluZWNyYWZ0OnNtYWxsX2FtZXRoeXN0X2J1ZAQJAG5hbWVfaGFzaEnb4+q9PO4YAwoAbmV0d29ya19pZGWzxrQKBgBzdGF0ZXMIFABtaW5lY3JhZnQ6YmxvY2tfZmFjZQIAdXAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:tuff", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRMAgAACAQAbmFtZQ4AbWluZWNyYWZ0OnR1ZmYECQBuYW1lX2hhc2h1Rwc1XYsBGwMKAG5ldHdvcmtfaWRwQGn0CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:tuff_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTpAwAACAQAbmFtZRUAbWluZWNyYWZ0OnR1ZmZfc3RhaXJzBAkAbmFtZV9oYXNoKjyNUBjcfZsDCgBuZXR3b3JrX2lk+LsycgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:tuff_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTnAwAACAQAbmFtZRMAbWluZWNyYWZ0OnR1ZmZfc2xhYgQJAG5hbWVfaGFzaIhCGdlIsnMUAwoAbmV0d29ya19pZN1dUL4KBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:tuff_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTqAwAACAQAbmFtZRMAbWluZWNyYWZ0OnR1ZmZfd2FsbAQJAG5hbWVfaGFzaMyeeu1IRf03AwoAbmV0d29ya19pZDkIrosKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:chiseled_tuff", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTwAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoaXNlbGVkX3R1ZmYECQBuYW1lX2hhc2iVliOT8OTQ9AMKAG5ldHdvcmtfaWTLNKOiCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:polished_tuff", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTrAwAACAQAbmFtZRcAbWluZWNyYWZ0OnBvbGlzaGVkX3R1ZmYECQBuYW1lX2hhc2hyaLe/KEVZ0gMKAG5ldHdvcmtfaWTcX3NrCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:polished_tuff_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTuAwAACAQAbmFtZR4AbWluZWNyYWZ0OnBvbGlzaGVkX3R1ZmZfc3RhaXJzBAkAbmFtZV9oYXNo8yuah8QI1dcDCgBuZXR3b3JrX2lkjLoU4AoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:polished_tuff_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTsAwAACAQAbmFtZRwAbWluZWNyYWZ0OnBvbGlzaGVkX3R1ZmZfc2xhYgQJAG5hbWVfaGFzaLXdb48YvAsHAwoAbmV0d29ya19pZAnJ7W0KBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:polished_tuff_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTvAwAACAQAbmFtZRwAbWluZWNyYWZ0OnBvbGlzaGVkX3R1ZmZfd2FsbAQJAG5hbWVfaGFzaJVZj6QYWXUrAwoAbmV0d29ya19pZLU7dooKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:tuff_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTxAwAACAQAbmFtZRUAbWluZWNyYWZ0OnR1ZmZfYnJpY2tzBAkAbmFtZV9oYXNo/hbQ+mXSK7wDCgBuZXR3b3JrX2lk6gmIwQoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:tuff_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT0AwAACAQAbmFtZRsAbWluZWNyYWZ0OnR1ZmZfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNoWJpkAurUfKwDCgBuZXR3b3JrX2lkUMcjiwoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:tuff_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTyAwAACAQAbmFtZRkAbWluZWNyYWZ0OnR1ZmZfYnJpY2tfc2xhYgQJAG5hbWVfaGFzaLqPMjVCv5dIAwoAbmV0d29ya19pZOmeRhcKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:tuff_brick_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT1AwAACAQAbmFtZRkAbWluZWNyYWZ0OnR1ZmZfYnJpY2tfd2FsbAQJAG5hbWVfaGFzaIL0IyNCOsonAwoAbmV0d29ya19pZJW4T5UKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:chiseled_tuff_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT2AwAACAQAbmFtZR4AbWluZWNyYWZ0OmNoaXNlbGVkX3R1ZmZfYnJpY2tzBAkAbmFtZV9oYXNo3oQw6gmxYuADCgBuZXR3b3JrX2lkm3D8AgoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:calcite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRFAgAACAQAbmFtZREAbWluZWNyYWZ0OmNhbGNpdGUECQBuYW1lX2hhc2ixKLu8ZIdzDQMKAG5ldHdvcmtfaWQlSbJDCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "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/FO78WDoDCgBuZXR3b3JrX2lkLh1OXAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:red_mushroom", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQoAAAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZF9tdXNocm9vbQQJAG5hbWVfaGFzaPpzJua7669xAwoAbmV0d29ya19pZCvWPYkKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:crimson_fungus", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fZnVuZ3VzBAkAbmFtZV9oYXNolIcCUuFM2u0DCgBuZXR3b3JrX2lkD2NN0QoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:warped_fungus", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9mdW5ndXMECQBuYW1lX2hhc2gq8bSnRVTAFgMKAG5ldHdvcmtfaWTkwS+rCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:brown_mushroom_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAAAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkdOMhDAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cw4AAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:red_mushroom_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRkAAAACAQAbmFtZRwAbWluZWNyYWZ0OnJlZF9tdXNocm9vbV9ibG9jawQJAG5hbWVfaGFzaJTTyJbth9M9AwoAbmV0d29ya19pZM+AyboKBgBzdGF0ZXMDEgBodWdlX211c2hyb29tX2JpdHMOAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:brown_mushroom_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAAAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkbdt3CAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cw8AAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:brown_mushroom_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAAAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkSrMl9goGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cwAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:egg" + }, + { + "id": "minecraft:sugar_cane" + }, + { + "id": "minecraft:sugar" + }, + { + "id": "minecraft:rotten_flesh" + }, + { + "id": "minecraft:bone" + }, + { + "id": "minecraft:web", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQeAAAACAQAbmFtZQ0AbWluZWNyYWZ0OndlYgQJAG5hbWVfaGFzaA4GKQCvG4i9AwoAbmV0d29ya19pZApt+jgKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:spider_eye" + }, + { + "id": "minecraft:mob_spawner", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ0AAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vYl9zcGF3bmVyBAkAbmFtZV9oYXNoNwGrCV/Fkh8DCgBuZXR3b3JrX2lkM1wTmgoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:trial_spawner", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ6AgAACAQAbmFtZRcAbWluZWNyYWZ0OnRyaWFsX3NwYXduZXIECQBuYW1lX2hhc2iNLRPB4ACz+QMKAG5ldHdvcmtfaWTWFYHGCgYAc3RhdGVzAQcAb21pbm91cwADEwB0cmlhbF9zcGF3bmVyX3N0YXRlAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:vault", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ5AgAACAQAbmFtZQ8AbWluZWNyYWZ0OnZhdWx0BAkAbmFtZV9oYXNoCAp9n3IAyqcDCgBuZXR3b3JrX2lk6/P+vwoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAQcAb21pbm91cwAICwB2YXVsdF9zdGF0ZQgAaW5hY3RpdmUAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:end_portal_frame", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR4AAAACAQAbmFtZRoAbWluZWNyYWZ0OmVuZF9wb3J0YWxfZnJhbWUECQBuYW1lX2hhc2gqofyUIjGOpQMKAG5ldHdvcmtfaWRbGHf8CgYAc3RhdGVzARIAZW5kX3BvcnRhbF9leWVfYml0AAgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:infested_stone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRgAbWluZWNyYWZ0OmluZmVzdGVkX3N0b25lBAkAbmFtZV9oYXNoxnRcHDu4zqQDCgBuZXR3b3JrX2lkpfcnsgoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:infested_cobblestone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRZBAAACAQAbmFtZR4AbWluZWNyYWZ0OmluZmVzdGVkX2NvYmJsZXN0b25lBAkAbmFtZV9oYXNoy+LVCKG2kVMDCgBuZXR3b3JrX2lkpn+icAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:infested_stone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRaBAAACAQAbmFtZR8AbWluZWNyYWZ0OmluZmVzdGVkX3N0b25lX2JyaWNrcwQJAG5hbWVfaGFzaBMnals7a32CAwoAbmV0d29ya19pZNHi2UYKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:infested_mossy_stone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRbBAAACAQAbmFtZSUAbWluZWNyYWZ0OmluZmVzdGVkX21vc3N5X3N0b25lX2JyaWNrcwQJAG5hbWVfaGFzaAmJk+HmVq0rAwoAbmV0d29ya19pZAVH8/sKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:infested_cracked_stone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRcBAAACAQAbmFtZScAbWluZWNyYWZ0OmluZmVzdGVkX2NyYWNrZWRfc3RvbmVfYnJpY2tzBAkAbmFtZV9oYXNoMyc60XcfcyoDCgBuZXR3b3JrX2lkaW+kbQoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:infested_chiseled_stone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRdBAAACAQAbmFtZSgAbWluZWNyYWZ0OmluZmVzdGVkX2NoaXNlbGVkX3N0b25lX2JyaWNrcwQJAG5hbWVfaGFzaNUvNIIg9dZbAwoAbmV0d29ya19pZCajGicKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:infested_deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTFAgAACAQAbmFtZRwAbWluZWNyYWZ0OmluZmVzdGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaICF2VYccxF1AwoAbmV0d29ya19pZDa/624KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:dragon_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR6AAAACAQAbmFtZRQAbWluZWNyYWZ0OmRyYWdvbl9lZ2cECQBuYW1lX2hhc2inMzXrV+/e1wMKAG5ldHdvcmtfaWTgO1yRCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:turtle_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAQAACAQAbmFtZRQAbWluZWNyYWZ0OnR1cnRsZV9lZ2cECQBuYW1lX2hhc2iwSRcxOJIJ9gMKAG5ldHdvcmtfaWSIRNUhCgYAc3RhdGVzCA0AY3JhY2tlZF9zdGF0ZQkAbm9fY3JhY2tzCBAAdHVydGxlX2VnZ19jb3VudAcAb25lX2VnZwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:sniffer_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRTAwAACAQAbmFtZRUAbWluZWNyYWZ0OnNuaWZmZXJfZWdnBAkAbmFtZV9oYXNoY1lozc8lPcYDCgBuZXR3b3JrX2lk7yb/2QoGAHN0YXRlcwgNAGNyYWNrZWRfc3RhdGUJAG5vX2NyYWNrcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:frog_spawn", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAgAACAQAbmFtZRQAbWluZWNyYWZ0OmZyb2dfc3Bhd24ECQBuYW1lX2hhc2iWmd7idp3ZZwMKAG5ldHdvcmtfaWRFzJudCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:pearlescent_froglight", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTUAgAACAQAbmFtZR8AbWluZWNyYWZ0OnBlYXJsZXNjZW50X2Zyb2dsaWdodAQJAG5hbWVfaGFzaKkcFRyycYGyAwoAbmV0d29ya19pZJqYakAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:verdant_froglight", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTVAgAACAQAbmFtZRsAbWluZWNyYWZ0OnZlcmRhbnRfZnJvZ2xpZ2h0BAkAbmFtZV9oYXNoA+eXuTBohrQDCgBuZXR3b3JrX2lkDIVnsQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:ochre_froglight", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTWAgAACAQAbmFtZRkAbWluZWNyYWZ0Om9jaHJlX2Zyb2dsaWdodAQJAG5hbWVfaGFzaMY59kjPe+c3AwoAbmV0d29ya19pZO2TD50KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "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:breeze_spawn_egg" + }, + { + "id": "minecraft:armadillo_spawn_egg" + }, + { + "id": "minecraft:bogged_spawn_egg" + }, + { + "id": "minecraft:obsidian", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQxAAAACAQAbmFtZRIAbWluZWNyYWZ0Om9ic2lkaWFuBAkAbmFtZV9oYXNoiz4qrb8QjyEDCgBuZXR3b3JrX2lkuqnPpQoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:crying_obsidian", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQgAgAACAQAbmFtZRkAbWluZWNyYWZ0OmNyeWluZ19vYnNpZGlhbgQJAG5hbWVfaGFzaKT0JlA7Z1K+AwoAbmV0d29ya19pZCjbPV4KBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:bedrock", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAAAACAQAbmFtZREAbWluZWNyYWZ0OmJlZHJvY2sECQBuYW1lX2hhc2hWfFrh4LVtxwMKAG5ldHdvcmtfaWT7fKz1CgYAc3RhdGVzAQ4AaW5maW5pYnVybl9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:soul_sand", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNvdWxfc2FuZAQJAG5hbWVfaGFzaMaf+bccu+KTAwoAbmV0d29ya19pZBQSHrMKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:magma", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTVAAAACAQAbmFtZQ8AbWluZWNyYWZ0Om1hZ21hBAkAbmFtZV9oYXNoqyTjKaIsWfYDCgBuZXR3b3JrX2lkyfWAZgoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:nether_wart" + }, + { + "id": "minecraft:end_stone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR5AAAACAQAbmFtZRMAbWluZWNyYWZ0OmVuZF9zdG9uZQQJAG5hbWVfaGFzaH1J9jA39GJNAwoAbmV0d29ya19pZFeFQ7UKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:chorus_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTIAAAACAQAbmFtZRcAbWluZWNyYWZ0OmNob3J1c19mbG93ZXIECQBuYW1lX2hhc2iMpSodli5uawMKAG5ldHdvcmtfaWRnd1ZWCgYAc3RhdGVzAwMAYWdlAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:chorus_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTwAAAACAQAbmFtZRYAbWluZWNyYWZ0OmNob3J1c19wbGFudAQJAG5hbWVfaGFzaJhSrmNGKwaMAwoAbmV0d29ya19pZA3uVqMKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:chorus_fruit" + }, + { + "id": "minecraft:popped_chorus_fruit" + }, + { + "id": "minecraft:sponge", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAAAACAQAbmFtZRAAbWluZWNyYWZ0OnNwb25nZQQJAG5hbWVfaGFzaLrd2ScYRDMiAwoAbmV0d29ya19pZF01rO0KBgBzdGF0ZXMICwBzcG9uZ2VfdHlwZQMAZHJ5AAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:sponge", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAAAACAQAbmFtZRAAbWluZWNyYWZ0OnNwb25nZQQJAG5hbWVfaGFzaLrd2ScYRDMiAwoAbmV0d29ya19pZPiOc4QKBgBzdGF0ZXMICwBzcG9uZ2VfdHlwZQMAd2V0AAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:tube_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRoAbWluZWNyYWZ0OnR1YmVfY29yYWxfYmxvY2sECQBuYW1lX2hhc2iGkaiR7Eot4wMKAG5ldHdvcmtfaWQPNJ6sCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:brain_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRQBAAACAQAbmFtZRsAbWluZWNyYWZ0OmJyYWluX2NvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoeDNAK18yUo4DCgBuZXR3b3JrX2lkloN1vgoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:bubble_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRRBAAACAQAbmFtZRwAbWluZWNyYWZ0OmJ1YmJsZV9jb3JhbF9ibG9jawQJAG5hbWVfaGFzaAI2mwMlvcNbAwoAbmV0d29ya19pZBlkxKIKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:fire_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRSBAAACAQAbmFtZRoAbWluZWNyYWZ0OmZpcmVfY29yYWxfYmxvY2sECQBuYW1lX2hhc2gg1gLeXLmKaAMKAG5ldHdvcmtfaWSp3W57CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:horn_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRTBAAACAQAbmFtZRoAbWluZWNyYWZ0Omhvcm5fY29yYWxfYmxvY2sECQBuYW1lX2hhc2hnZSLRWUwGhAMKAG5ldHdvcmtfaWRSK6ccCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:dead_tube_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRUBAAACAQAbmFtZR8AbWluZWNyYWZ0OmRlYWRfdHViZV9jb3JhbF9ibG9jawQJAG5hbWVfaGFzaB9+lY3hAkNNAwoAbmV0d29ya19pZF0hKKYKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:dead_brain_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRVBAAACAQAbmFtZSAAbWluZWNyYWZ0OmRlYWRfYnJhaW5fY29yYWxfYmxvY2sECQBuYW1lX2hhc2iHyDn52AO8uwMKAG5ldHdvcmtfaWQw7yCaCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:dead_bubble_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRWBAAACAQAbmFtZSEAbWluZWNyYWZ0OmRlYWRfYnViYmxlX2NvcmFsX2Jsb2NrBAkAbmFtZV9oYXNotwkk/ITrsjADCgBuZXR3b3JrX2lk56mXUgoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:dead_fire_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRXBAAACAQAbmFtZR8AbWluZWNyYWZ0OmRlYWRfZmlyZV9jb3JhbF9ibG9jawQJAG5hbWVfaGFzaG0qHxbIrBEyAwoAbmV0d29ya19pZFvnH88KBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:dead_horn_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRYBAAACAQAbmFtZR8AbWluZWNyYWZ0OmRlYWRfaG9ybl9jb3JhbF9ibG9jawQJAG5hbWVfaGFzaL7D8bu4Fm+0AwoAbmV0d29ya19pZEALRLoKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:sculk", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAgAACAQAbmFtZQ8AbWluZWNyYWZ0OnNjdWxrBAkAbmFtZV9oYXNo2Lq7T5yQF8kDCgBuZXR3b3JrX2lkyqUPPgoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:sculk_vein", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTKAgAACAQAbmFtZRQAbWluZWNyYWZ0OnNjdWxrX3ZlaW4ECQBuYW1lX2hhc2gJUdhVooV4zwMKAG5ldHdvcmtfaWSUfn1XCgYAc3RhdGVzAxkAbXVsdGlfZmFjZV9kaXJlY3Rpb25fYml0cwAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:sculk_catalyst", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAgAACAQAbmFtZRgAbWluZWNyYWZ0OnNjdWxrX2NhdGFseXN0BAkAbmFtZV9oYXNo+gCpbrCHST4DCgBuZXR3b3JrX2lkMJ2n/woGAHN0YXRlcwEFAGJsb29tAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:sculk_shrieker", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTMAgAACAQAbmFtZRgAbWluZWNyYWZ0OnNjdWxrX3Nocmlla2VyBAkAbmFtZV9oYXNo5OXtyObniQ4DCgBuZXR3b3JrX2lkxapoNAoGAHN0YXRlcwEGAGFjdGl2ZQABCgBjYW5fc3VtbW9uAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:sculk_sensor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQyAgAACAQAbmFtZRYAbWluZWNyYWZ0OnNjdWxrX3NlbnNvcgQJAG5hbWVfaGFzaCkmHreeTgNnAwoAbmV0d29ya19pZLj2WPcKBgBzdGF0ZXMDEgBzY3Vsa19zZW5zb3JfcGhhc2UAAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:calibrated_sculk_sensor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRDAwAACAQAbmFtZSEAbWluZWNyYWZ0OmNhbGlicmF0ZWRfc2N1bGtfc2Vuc29yBAkAbmFtZV9oYXNoffAcXXN/iJUDCgBuZXR3b3JrX2lkwOx3QQoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAxIAc2N1bGtfc2Vuc29yX3BoYXNlAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:reinforced_deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTRAgAACAQAbmFtZR4AbWluZWNyYWZ0OnJlaW5mb3JjZWRfZGVlcHNsYXRlBAkAbmFtZV9oYXNoldDmj91EapQDCgBuZXR3b3JrX2lkHIt+aQoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "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:mace" + }, + { + "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: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" + }, + { + "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:wind_charge" + }, + { + "id": "minecraft:shears" + }, + { + "id": "minecraft:flint_and_steel" + }, + { + "id": "minecraft:lead" + }, + { + "id": "minecraft:clock" + }, + { + "id": "minecraft:compass" + }, + { + "id": "minecraft:recovery_compass" + }, + { + "id": "minecraft:goat_horn" + }, + { + "id": "minecraft:goat_horn", + "damage": 1 + }, + { + "id": "minecraft:goat_horn", + "damage": 2 + }, + { + "id": "minecraft:goat_horn", + "damage": 3 + }, + { + "id": "minecraft:goat_horn", + "damage": 4 + }, + { + "id": "minecraft:goat_horn", + "damage": 5 + }, + { + "id": "minecraft:goat_horn", + "damage": 6 + }, + { + "id": "minecraft:goat_horn", + "damage": 7 + }, + { + "id": "minecraft:empty_map" + }, + { + "id": "minecraft:empty_map", + "damage": 2 + }, + { + "id": "minecraft:saddle" + }, + { + "id": "minecraft:leather_horse_armor" + }, + { + "id": "minecraft:iron_horse_armor" + }, + { + "id": "minecraft:golden_horse_armor" + }, + { + "id": "minecraft:diamond_horse_armor" + }, + { + "id": "minecraft:wolf_armor" + }, + { + "id": "minecraft:trident" + }, + { + "id": "minecraft:turtle_helmet" + }, + { + "id": "minecraft:elytra" + }, + { + "id": "minecraft:totem_of_undying" + }, + { + "id": "minecraft:glass_bottle" + }, + { + "id": "minecraft:experience_bottle" + }, + { + "id": "minecraft:potion" + }, + { + "id": "minecraft:potion", + "damage": 1 + }, + { + "id": "minecraft:potion", + "damage": 2 + }, + { + "id": "minecraft:potion", + "damage": 3 + }, + { + "id": "minecraft:potion", + "damage": 4 + }, + { + "id": "minecraft:potion", + "damage": 5 + }, + { + "id": "minecraft:potion", + "damage": 6 + }, + { + "id": "minecraft:potion", + "damage": 7 + }, + { + "id": "minecraft:potion", + "damage": 8 + }, + { + "id": "minecraft:potion", + "damage": 9 + }, + { + "id": "minecraft:potion", + "damage": 10 + }, + { + "id": "minecraft:potion", + "damage": 11 + }, + { + "id": "minecraft:potion", + "damage": 12 + }, + { + "id": "minecraft:potion", + "damage": 13 + }, + { + "id": "minecraft:potion", + "damage": 14 + }, + { + "id": "minecraft:potion", + "damage": 15 + }, + { + "id": "minecraft:potion", + "damage": 16 + }, + { + "id": "minecraft:potion", + "damage": 17 + }, + { + "id": "minecraft:potion", + "damage": 18 + }, + { + "id": "minecraft:potion", + "damage": 19 + }, + { + "id": "minecraft:potion", + "damage": 20 + }, + { + "id": "minecraft:potion", + "damage": 21 + }, + { + "id": "minecraft:potion", + "damage": 22 + }, + { + "id": "minecraft:potion", + "damage": 23 + }, + { + "id": "minecraft:potion", + "damage": 24 + }, + { + "id": "minecraft:potion", + "damage": 25 + }, + { + "id": "minecraft:potion", + "damage": 26 + }, + { + "id": "minecraft:potion", + "damage": 27 + }, + { + "id": "minecraft:potion", + "damage": 28 + }, + { + "id": "minecraft:potion", + "damage": 29 + }, + { + "id": "minecraft:potion", + "damage": 30 + }, + { + "id": "minecraft:potion", + "damage": 31 + }, + { + "id": "minecraft:potion", + "damage": 32 + }, + { + "id": "minecraft:potion", + "damage": 33 + }, + { + "id": "minecraft:potion", + "damage": 34 + }, + { + "id": "minecraft:potion", + "damage": 35 + }, + { + "id": "minecraft:potion", + "damage": 36 + }, + { + "id": "minecraft:potion", + "damage": 37 + }, + { + "id": "minecraft:potion", + "damage": 38 + }, + { + "id": "minecraft:potion", + "damage": 39 + }, + { + "id": "minecraft:potion", + "damage": 40 + }, + { + "id": "minecraft:potion", + "damage": 41 + }, + { + "id": "minecraft:potion", + "damage": 42 + }, + { + "id": "minecraft:potion", + "damage": 43 + }, + { + "id": "minecraft:potion", + "damage": 44 + }, + { + "id": "minecraft:potion", + "damage": 45 + }, + { + "id": "minecraft:potion", + "damage": 46 + }, + { + "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: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" + }, + { + "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: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" + }, + { + "id": "minecraft:brush" + }, + { + "id": "minecraft:stick" + }, + { + "id": "minecraft:bed" + }, + { + "id": "minecraft:bed", + "damage": 8 + }, + { + "id": "minecraft:bed", + "damage": 7 + }, + { + "id": "minecraft:bed", + "damage": 15 + }, + { + "id": "minecraft:bed", + "damage": 12 + }, + { + "id": "minecraft:bed", + "damage": 14 + }, + { + "id": "minecraft:bed", + "damage": 1 + }, + { + "id": "minecraft:bed", + "damage": 4 + }, + { + "id": "minecraft:bed", + "damage": 5 + }, + { + "id": "minecraft:bed", + "damage": 13 + }, + { + "id": "minecraft:bed", + "damage": 9 + }, + { + "id": "minecraft:bed", + "damage": 3 + }, + { + "id": "minecraft:bed", + "damage": 11 + }, + { + "id": "minecraft:bed", + "damage": 10 + }, + { + "id": "minecraft:bed", + "damage": 2 + }, + { + "id": "minecraft:bed", + "damage": 6 + }, + { + "id": "minecraft:torch", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQyAAAACAQAbmFtZQ8AbWluZWNyYWZ0OnRvcmNoBAkAbmFtZV9oYXNoagn7rmDBzisDCgBuZXR3b3JrX2lk+BwwuQoGAHN0YXRlcwgWAHRvcmNoX2ZhY2luZ19kaXJlY3Rpb24HAHVua25vd24AAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:soul_torch", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQLAgAACAQAbmFtZRQAbWluZWNyYWZ0OnNvdWxfdG9yY2gECQBuYW1lX2hhc2huixOT04BRdQMKAG5ldHdvcmtfaWShbFILCgYAc3RhdGVzCBYAdG9yY2hfZmFjaW5nX2RpcmVjdGlvbgcAdW5rbm93bgADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:sea_pickle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAQAACAQAbmFtZRQAbWluZWNyYWZ0OnNlYV9waWNrbGUECQBuYW1lX2hhc2iONEfZJB+glgMKAG5ldHdvcmtfaWSINWQyCgYAc3RhdGVzAw0AY2x1c3Rlcl9jb3VudAAAAAABCABkZWFkX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:lantern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTPAQAACAQAbmFtZREAbWluZWNyYWZ0OmxhbnRlcm4ECQBuYW1lX2hhc2hMw44VI2HWygMKAG5ldHdvcmtfaWRkjQvzCgYAc3RhdGVzAQcAaGFuZ2luZwAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:soul_lantern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQMAgAACAQAbmFtZRYAbWluZWNyYWZ0OnNvdWxfbGFudGVybgQJAG5hbWVfaGFzaGjIpjxk9z+RAwoAbmV0d29ya19pZGfoP8cKBgBzdGF0ZXMBBwBoYW5naW5nAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAgAACAQAbmFtZRAAbWluZWNyYWZ0OmNhbmRsZQQJAG5hbWVfaGFzaHPd+MsNdWTfAwoAbmV0d29ya19pZHsBMA0KBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:white_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWScAgAACAQAbmFtZRYAbWluZWNyYWZ0OndoaXRlX2NhbmRsZQQJAG5hbWVfaGFzaN1EG5Q1mHiEAwoAbmV0d29ya19pZKN1mmgKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:orange_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSdAgAACAQAbmFtZRcAbWluZWNyYWZ0Om9yYW5nZV9jYW5kbGUECQBuYW1lX2hhc2jySEVWHgUIHQMKAG5ldHdvcmtfaWSfVz82CgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:magenta_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hZ2VudGFfY2FuZGxlBAkAbmFtZV9oYXNoG0u6YIOoBSEDCgBuZXR3b3JrX2lk9xGNkQoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:light_blue_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSfAgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY2FuZGxlBAkAbmFtZV9oYXNocXGeK0zgrG0DCgBuZXR3b3JrX2lk2m1y8goGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:yellow_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSgAgAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19jYW5kbGUECQBuYW1lX2hhc2i00dtusU3CqQMKAG5ldHdvcmtfaWR9LTmpCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:lime_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAgAACAQAbmFtZRUAbWluZWNyYWZ0OmxpbWVfY2FuZGxlBAkAbmFtZV9oYXNokcmrw5xvz7ADCgBuZXR3b3JrX2lkIAUu6QoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:pink_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAgAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfY2FuZGxlBAkAbmFtZV9oYXNoQJdEY4sZ0dwDCgBuZXR3b3JrX2lk23Rn5AoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:gray_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSjAgAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXlfY2FuZGxlBAkAbmFtZV9oYXNoS5poSo9wBDEDCgBuZXR3b3JrX2lk3trRCAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:light_gray_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY2FuZGxlBAkAbmFtZV9oYXNo9ruTZLBNMasDCgBuZXR3b3JrX2lkb6DOegoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:cyan_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAgAACAQAbmFtZRUAbWluZWNyYWZ0OmN5YW5fY2FuZGxlBAkAbmFtZV9oYXNoc/M8PNVcjOwDCgBuZXR3b3JrX2lkZoIQOQoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:purple_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSmAgAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnBsZV9jYW5kbGUECQBuYW1lX2hhc2jaI3xUW0/myQMKAG5ldHdvcmtfaWSnLI2BCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:blue_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSnAgAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfY2FuZGxlBAkAbmFtZV9oYXNoAASSPW6TgQADCgBuZXR3b3JrX2lkrxrjQAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:brown_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAgAACAQAbmFtZRYAbWluZWNyYWZ0OmJyb3duX2NhbmRsZQQJAG5hbWVfaGFzaDia0l6s1+WYAwoAbmV0d29ya19pZKSkBXYKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:green_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAgAACAQAbmFtZRYAbWluZWNyYWZ0OmdyZWVuX2NhbmRsZQQJAG5hbWVfaGFzaLeFPO1l+fIoAwoAbmV0d29ya19pZBkznDsKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:red_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9jYW5kbGUECQBuYW1lX2hhc2jjAQpGf59ZdwMKAG5ldHdvcmtfaWRbb88GCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:black_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAgAACAQAbmFtZRYAbWluZWNyYWZ0OmJsYWNrX2NhbmRsZQQJAG5hbWVfaGFzaB+wRDpOqREKAwoAbmV0d29ya19pZNnOnuEKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:crafting_table", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ6AAAACAQAbmFtZRgAbWluZWNyYWZ0OmNyYWZ0aW5nX3RhYmxlBAkAbmFtZV9oYXNoe76VAmjvbpYDCgBuZXR3b3JrX2lkwCxwaAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:cartography_table", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTHAQAACAQAbmFtZRsAbWluZWNyYWZ0OmNhcnRvZ3JhcGh5X3RhYmxlBAkAbmFtZV9oYXNomaWiiD/znP8DCgBuZXR3b3JrX2lkI6FzMwoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:fletching_table", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTIAQAACAQAbmFtZRkAbWluZWNyYWZ0OmZsZXRjaGluZ190YWJsZQQJAG5hbWVfaGFzaPFibh8unKyUAwoAbmV0d29ya19pZJ2mW0oKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:smithing_table", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAQAACAQAbmFtZRgAbWluZWNyYWZ0OnNtaXRoaW5nX3RhYmxlBAkAbmFtZV9oYXNo4tFES2xOXEYDCgBuZXR3b3JrX2lkXWMBzQoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:beehive", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAQAACAQAbmFtZREAbWluZWNyYWZ0OmJlZWhpdmUECQBuYW1lX2hhc2hCcqn12UbNpwMKAG5ldHdvcmtfaWR/idcaCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAMLAGhvbmV5X2xldmVsAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:suspicious_sand", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQQAwAACAQAbmFtZRkAbWluZWNyYWZ0OnN1c3BpY2lvdXNfc2FuZAQJAG5hbWVfaGFzaL67QsuvLP00AwoAbmV0d29ya19pZKnkaIAKBgBzdGF0ZXMDEABicnVzaGVkX3Byb2dyZXNzAAAAAAEHAGhhbmdpbmcBAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:suspicious_gravel", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ8AwAACAQAbmFtZRsAbWluZWNyYWZ0OnN1c3BpY2lvdXNfZ3JhdmVsBAkAbmFtZV9oYXNoJSVbGNk7C3oDCgBuZXR3b3JrX2lkvIEJAAoGAHN0YXRlcwMQAGJydXNoZWRfcHJvZ3Jlc3MAAAAAAQcAaGFuZ2luZwEAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:campfire" + }, + { + "id": "minecraft:soul_campfire" + }, + { + "id": "minecraft:furnace", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ9AAAACAQAbmFtZREAbWluZWNyYWZ0OmZ1cm5hY2UECQBuYW1lX2hhc2ioOQrludYY8wMKAG5ldHdvcmtfaWRZxnDOCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:blast_furnace", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTDAQAACAQAbmFtZRcAbWluZWNyYWZ0OmJsYXN0X2Z1cm5hY2UECQBuYW1lX2hhc2ivDbnjkpGm5QMKAG5ldHdvcmtfaWTcEbV/CgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:smoker", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTFAQAACAQAbmFtZRAAbWluZWNyYWZ0OnNtb2tlcgQJAG5hbWVfaGFzaJd1rDMkRWomAwoAbmV0d29ya19pZGWswMwKBgBzdGF0ZXMIHABtaW5lY3JhZnQ6Y2FyZGluYWxfZGlyZWN0aW9uBQBzb3V0aAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:respawn_anchor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQPAgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlc3Bhd25fYW5jaG9yBAkAbmFtZV9oYXNoZOdcjW05qigDCgBuZXR3b3JrX2lkmhMcaQoGAHN0YXRlcwMVAHJlc3Bhd25fYW5jaG9yX2NoYXJnZQAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:brewing_stand" + }, + { + "id": "minecraft:anvil", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lkqXzNjwoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:chipped_anvil", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS+BAAACAQAbmFtZRcAbWluZWNyYWZ0OmNoaXBwZWRfYW52aWwECQBuYW1lX2hhc2ge+QY3vlS/eQMKAG5ldHdvcmtfaWRJ15iUCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:damaged_anvil", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS/BAAACAQAbmFtZRcAbWluZWNyYWZ0OmRhbWFnZWRfYW52aWwECQBuYW1lX2hhc2imJ12Be2V8+AMKAG5ldHdvcmtfaWRh5SHkCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:grindstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTCAQAACAQAbmFtZRQAbWluZWNyYWZ0OmdyaW5kc3RvbmUECQBuYW1lX2hhc2id56zc0nk99wMKAG5ldHdvcmtfaWS4Es07CgYAc3RhdGVzCAoAYXR0YWNobWVudAgAc3RhbmRpbmcDCQBkaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:enchanting_table", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR0AAAACAQAbmFtZRoAbWluZWNyYWZ0OmVuY2hhbnRpbmdfdGFibGUECQBuYW1lX2hhc2jgIx24VLvMvwMKAG5ldHdvcmtfaWRliFFJCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:bookshelf", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQvAAAACAQAbmFtZRMAbWluZWNyYWZ0OmJvb2tzaGVsZgQJAG5hbWVfaGFzaDU04DrgJCS9AwoAbmV0d29ya19pZBcWwIwKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:chiseled_bookshelf", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQNAwAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX2Jvb2tzaGVsZgQJAG5hbWVfaGFzaNXDBnsIsywYAwoAbmV0d29ya19pZIprt5IKBgBzdGF0ZXMDDABib29rc19zdG9yZWQAAAAAAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:lectern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTBAQAACAQAbmFtZREAbWluZWNyYWZ0OmxlY3Rlcm4ECQBuYW1lX2hhc2j5Z4Mmi/1QxAMKAG5ldHdvcmtfaWR4JfDHCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgBCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:cauldron" + }, + { + "id": "minecraft:composter", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTUAQAACAQAbmFtZRMAbWluZWNyYWZ0OmNvbXBvc3RlcgQJAG5hbWVfaGFzaPAADHptzeWJAwoAbmV0d29ya19pZHIL6i4KBgBzdGF0ZXMDFABjb21wb3N0ZXJfZmlsbF9sZXZlbAAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:chest", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ2AAAACAQAbmFtZQ8AbWluZWNyYWZ0OmNoZXN0BAkAbmFtZV9oYXNog9ozMxlcA88DCgBuZXR3b3JrX2lkDkOFvAoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:trapped_chest", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSSAAAACAQAbmFtZRcAbWluZWNyYWZ0OnRyYXBwZWRfY2hlc3QECQBuYW1lX2hhc2g2qpF9stsEjgMKAG5ldHdvcmtfaWTjJWYxCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAbm9ydGgAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:ender_chest", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAAAACAQAbmFtZRUAbWluZWNyYWZ0OmVuZGVyX2NoZXN0BAkAbmFtZV9oYXNohEZzOFdg0WUDCgBuZXR3b3JrX2lkx4jiSQoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:barrel", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTKAQAACAQAbmFtZRAAbWluZWNyYWZ0OmJhcnJlbAQJAG5hbWVfaGFzaHDkRPGymiRqAwoAbmV0d29ya19pZPnxzgsKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:undyed_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTNAAAACAQAbmFtZRwAbWluZWNyYWZ0OnVuZHllZF9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaOC9mypm/MlBAwoAbmV0d29ya19pZJ8rxp0KBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:white_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAAAACAQAbmFtZRsAbWluZWNyYWZ0OndoaXRlX3NodWxrZXJfYm94BAkAbmFtZV9oYXNosK79m1rPUBwDCgBuZXR3b3JrX2lkjrET6goGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:light_gray_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRrAwAACAQAbmFtZSAAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2iBe5zq7PxHmgMKAG5ldHdvcmtfaWSCVJv0CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:gray_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRqAwAACAQAbmFtZRoAbWluZWNyYWZ0OmdyYXlfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2ga2s8ctjHUhgMKAG5ldHdvcmtfaWS3WMsWCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:black_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRyAwAACAQAbmFtZRsAbWluZWNyYWZ0OmJsYWNrX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoPm03OZphrp8DCgBuZXR3b3JrX2lkXHztNAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:brown_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRvAwAACAQAbmFtZRsAbWluZWNyYWZ0OmJyb3duX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoT3DD6qAL9cADCgBuZXR3b3JrX2lkaXxpYQoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:red_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRxAwAACAQAbmFtZRkAbWluZWNyYWZ0OnJlZF9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaMIlKSCzqSZoAwoAbmV0d29ya19pZNrf+icKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:orange_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRkAwAACAQAbmFtZRwAbWluZWNyYWZ0Om9yYW5nZV9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaG2MAXU67wGrAwoAbmV0d29ya19pZGoO05gKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:yellow_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRnAwAACAQAbmFtZRwAbWluZWNyYWZ0OnllbGxvd19zaHVsa2VyX2JveAQJAG5hbWVfaGFzaIsLwQHYjcIEAwoAbmV0d29ya19pZBCBSiYKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:lime_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRoAwAACAQAbmFtZRoAbWluZWNyYWZ0OmxpbWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2hUwBkg+faUGAMKAG5ldHdvcmtfaWRJeKqqCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:green_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRwAwAACAQAbmFtZRsAbWluZWNyYWZ0OmdyZWVuX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoZgUeT3LupLUDCgBuZXR3b3JrX2lkzJiohQoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:cyan_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRsAwAACAQAbmFtZRoAbWluZWNyYWZ0OmN5YW5fc2h1bGtlcl9ib3gECQBuYW1lX2hhc2gSfbjteXg5yAMKAG5ldHdvcmtfaWTHeliECgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:light_blue_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRmAwAACAQAbmFtZSAAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2h0VFCX0qsRxQMKAG5ldHdvcmtfaWQXD8U0CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:blue_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRuAwAACAQAbmFtZRoAbWluZWNyYWZ0OmJsdWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2hn9gS0XIe6rAMKAG5ldHdvcmtfaWTO4PJaCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:purple_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRtAwAACAQAbmFtZRwAbWluZWNyYWZ0OnB1cnBsZV9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaEV/lkNPxRDdAwoAbmV0d29ya19pZFK25GAKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:magenta_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRlAwAACAQAbmFtZR0AbWluZWNyYWZ0Om1hZ2VudGFfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2iqWM7IJHxcFgMKAG5ldHdvcmtfaWTyyudTCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:pink_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRpAwAACAQAbmFtZRoAbWluZWNyYWZ0OnBpbmtfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2in1tkJ1GNcZgMKAG5ldHdvcmtfaWQOEGXjCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:armor_stand" + }, + { + "id": "minecraft:noteblock", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQZAAAACAQAbmFtZRMAbWluZWNyYWZ0Om5vdGVibG9jawQJAG5hbWVfaGFzaHPA8dBBH0UaAwoAbmV0d29ya19pZH1U5QkKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:jukebox", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRUAAAACAQAbmFtZREAbWluZWNyYWZ0Omp1a2Vib3gECQBuYW1lX2hhc2ieAIPExf/ZfgMKAG5ldHdvcmtfaWSmR7JfCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "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:music_disc_creator" + }, + { + "id": "minecraft:music_disc_creator_music_box" + }, + { + "id": "minecraft:music_disc_precipice" + }, + { + "id": "minecraft:disc_fragment_5" + }, + { + "id": "minecraft:glowstone_dust" + }, + { + "id": "minecraft:glowstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRZAAAACAQAbmFtZRMAbWluZWNyYWZ0Omdsb3dzdG9uZQQJAG5hbWVfaGFzaFYqXNkefIlPAwoAbmV0d29ya19pZGT7WYYKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:redstone_lamp", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR7AAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZHN0b25lX2xhbXAECQBuYW1lX2hhc2hJ9V80caPvEgMKAG5ldHdvcmtfaWRvNPwnCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:sea_lantern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAAAACAQAbmFtZRUAbWluZWNyYWZ0OnNlYV9sYW50ZXJuBAkAbmFtZV9oYXNoLPsv1TX9M+QDCgBuZXR3b3JrX2lk1PPVyAoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "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": "CgAAAwgAYmxvY2tfaWSKAAAACAQAbmFtZRAAbWluZWNyYWZ0OmJlYWNvbgQJAG5hbWVfaGFzaACwhhfSkdkHAwoAbmV0d29ya19pZF8jfiEKBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:bell", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTNAQAACAQAbmFtZQ4AbWluZWNyYWZ0OmJlbGwECQBuYW1lX2hhc2iPqsgDXRcsxAMKAG5ldHdvcmtfaWT7zhOoCgYAc3RhdGVzCAoAYXR0YWNobWVudAgAc3RhbmRpbmcDCQBkaXJlY3Rpb24AAAAAAQoAdG9nZ2xlX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:conduit", + "block_state_b64": "CgAAAwgAYmxvY2tfaWScAQAACAQAbmFtZREAbWluZWNyYWZ0OmNvbmR1aXQECQBuYW1lX2hhc2jqxKAxq2EaWQMKAG5ldHdvcmtfaWTWcBVnCgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:stonecutter_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTEAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lY3V0dGVyX2Jsb2NrBAkAbmFtZV9oYXNoQAXTbAM3MeYDCgBuZXR3b3JrX2lkWS4RjAoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:coal" + }, + { + "id": "minecraft:charcoal" + }, + { + "id": "minecraft:diamond" + }, + { + "id": "minecraft:iron_nugget" + }, + { + "id": "minecraft:raw_iron" + }, + { + "id": "minecraft:raw_gold" + }, + { + "id": "minecraft:raw_copper" + }, + { + "id": "minecraft:copper_ingot" + }, + { + "id": "minecraft:iron_ingot" + }, + { + "id": "minecraft:netherite_scrap" + }, + { + "id": "minecraft:netherite_ingot" + }, + { + "id": "minecraft:gold_nugget" + }, + { + "id": "minecraft:gold_ingot" + }, + { + "id": "minecraft:emerald" + }, + { + "id": "minecraft:quartz" + }, + { + "id": "minecraft:clay_ball" + }, + { + "id": "minecraft:brick" + }, + { + "id": "minecraft:netherbrick" + }, + { + "id": "minecraft:prismarine_shard" + }, + { + "id": "minecraft:amethyst_shard" + }, + { + "id": "minecraft:prismarine_crystals" + }, + { + "id": "minecraft:nautilus_shell" + }, + { + "id": "minecraft:heart_of_the_sea" + }, + { + "id": "minecraft:turtle_scute" + }, + { + "id": "minecraft:armadillo_scute" + }, + { + "id": "minecraft:phantom_membrane" + }, + { + "id": "minecraft:string" + }, + { + "id": "minecraft:feather" + }, + { + "id": "minecraft:flint" + }, + { + "id": "minecraft:gunpowder" + }, + { + "id": "minecraft:leather" + }, + { + "id": "minecraft:rabbit_hide" + }, + { + "id": "minecraft:rabbit_foot" + }, + { + "id": "minecraft:fire_charge" + }, + { + "id": "minecraft:blaze_rod" + }, + { + "id": "minecraft:breeze_rod" + }, + { + "id": "minecraft:heavy_core", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ7AgAACAQAbmFtZRQAbWluZWNyYWZ0OmhlYXZ5X2NvcmUECQBuYW1lX2hhc2hhz/uNCtrC2QMKAG5ldHdvcmtfaWRaFu+8CgYAc3RhdGVzAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "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/q5cEA0hmQMKAG5ldHdvcmtfaWQ2eM8kCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:lightning_rod", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ3AgAACAQAbmFtZRcAbWluZWNyYWZ0OmxpZ2h0bmluZ19yb2QECQBuYW1lX2hhc2ioXQF1xvfHNQMKAG5ldHdvcmtfaWRLuHyACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:end_crystal" + }, + { + "id": "minecraft:paper" + }, + { + "id": "minecraft:book" + }, + { + "id": "minecraft:writable_book" + }, + { + "id": "minecraft:trial_key" + }, + { + "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: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" + }, + { + "id": "minecraft:spruce_boat" + }, + { + "id": "minecraft:birch_boat" + }, + { + "id": "minecraft:jungle_boat" + }, + { + "id": "minecraft:acacia_boat" + }, + { + "id": "minecraft:dark_oak_boat" + }, + { + "id": "minecraft:mangrove_boat" + }, + { + "id": "minecraft:cherry_boat" + }, + { + "id": "minecraft:bamboo_raft" + }, + { + "id": "minecraft:oak_chest_boat" + }, + { + "id": "minecraft:spruce_chest_boat" + }, + { + "id": "minecraft:birch_chest_boat" + }, + { + "id": "minecraft:jungle_chest_boat" + }, + { + "id": "minecraft:acacia_chest_boat" + }, + { + "id": "minecraft:dark_oak_chest_boat" + }, + { + "id": "minecraft:mangrove_chest_boat" + }, + { + "id": "minecraft:cherry_chest_boat" + }, + { + "id": "minecraft:bamboo_chest_raft" + }, + { + "id": "minecraft:rail", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRCAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnJhaWwECQBuYW1lX2hhc2hUzmhUXYJDUQMKAG5ldHdvcmtfaWR+Sp6YCgYAc3RhdGVzAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:golden_rail", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQbAAAACAQAbmFtZRUAbWluZWNyYWZ0OmdvbGRlbl9yYWlsBAkAbmFtZV9oYXNoOoV5MaKipoUDCgBuZXR3b3JrX2lkfAcxLwoGAHN0YXRlcwENAHJhaWxfZGF0YV9iaXQAAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:detector_rail", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQcAAAACAQAbmFtZRcAbWluZWNyYWZ0OmRldGVjdG9yX3JhaWwECQBuYW1lX2hhc2gVUk31qOysUQMKAG5ldHdvcmtfaWRVW/aICgYAc3RhdGVzAQ0AcmFpbF9kYXRhX2JpdAADDgByYWlsX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:activator_rail", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR+AAAACAQAbmFtZRgAbWluZWNyYWZ0OmFjdGl2YXRvcl9yYWlsBAkAbmFtZV9oYXNosIL91qriCRkDCgBuZXR3b3JrX2lkZfckmwoGAHN0YXRlcwENAHJhaWxfZGF0YV9iaXQAAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "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": "CgAAAwgAYmxvY2tfaWSYAAAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZHN0b25lX2Jsb2NrBAkAbmFtZV9oYXNoRhULL0r8o0sDCgBuZXR3b3JrX2lklayOHgoGAHN0YXRlcwADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:redstone_torch", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRMAAAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZHN0b25lX3RvcmNoBAkAbmFtZV9oYXNoizFRjpYMIDgDCgBuZXR3b3JrX2lkuHz7yAoGAHN0YXRlcwgWAHRvcmNoX2ZhY2luZ19kaXJlY3Rpb24HAHVua25vd24AAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:lever", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRFAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmxldmVyBAkAbmFtZV9oYXNoGMJeLJsUMLYDCgBuZXR3b3JrX2lkEF/GuAoGAHN0YXRlcwgPAGxldmVyX2RpcmVjdGlvbg4AZG93bl9lYXN0X3dlc3QBCABvcGVuX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:wooden_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAAAACAQAbmFtZRcAbWluZWNyYWZ0Ondvb2Rlbl9idXR0b24ECQBuYW1lX2hhc2hR7PgSTQt0sQMKAG5ldHdvcmtfaWSU07kYCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:spruce_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAQAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9idXR0b24ECQBuYW1lX2hhc2jBW9Z8aYE7YQMKAG5ldHdvcmtfaWTkUIGuCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:birch_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSMAQAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX2J1dHRvbgQJAG5hbWVfaGFzaJXYgGuSHbTwAwoAbmV0d29ya19pZGWp3yoKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:jungle_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSOAQAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9idXR0b24ECQBuYW1lX2hhc2iCgNANcJs+BQMKAG5ldHdvcmtfaWT9fImWCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:acacia_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAQAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9idXR0b24ECQBuYW1lX2hhc2gVvmcT7LTO0wMKAG5ldHdvcmtfaWRQnxIJCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:dark_oak_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSNAQAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX2J1dHRvbgQJAG5hbWVfaGFzaIV10ZGGrCIEAwoAbmV0d29ya19pZN5vAmIKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:mangrove_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTmAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX2J1dHRvbgQJAG5hbWVfaGFzaNzeYYKLgOzJAwoAbmV0d29ya19pZAFEGQ0KBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:cherry_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQRAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9idXR0b24ECQBuYW1lX2hhc2j2/IHjeAbUcwMKAG5ldHdvcmtfaWRJ1irQCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:bamboo_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT+AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19idXR0b24ECQBuYW1lX2hhc2j7AddMi+6nsgMKAG5ldHdvcmtfaWSa9w4/CgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:stone_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRNAAAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX2J1dHRvbgQJAG5hbWVfaGFzaM4ejMctmvohAwoAbmV0d29ya19pZMw+aC0KBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:crimson_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fYnV0dG9uBAkAbmFtZV9oYXNofnjYHaYIeWgDCgBuZXR3b3JrX2lk+n1vyQoGAHN0YXRlcwESAGJ1dHRvbl9wcmVzc2VkX2JpdAADEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:warped_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQEAgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9idXR0b24ECQBuYW1lX2hhc2jwkV2EU6Cn1QMKAG5ldHdvcmtfaWTnHnk1CgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:polished_blackstone_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQnAgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnV0dG9uBAkAbmFtZV9oYXNojmxzQKS0S/EDCgBuZXR3b3JrX2lkDtQ95woGAHN0YXRlcwESAGJ1dHRvbl9wcmVzc2VkX2JpdAADEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:tripwire_hook", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAAAACAQAbmFtZRcAbWluZWNyYWZ0OnRyaXB3aXJlX2hvb2sECQBuYW1lX2hhc2gQdp+oGZLNnAMKAG5ldHdvcmtfaWSy+1KJCgYAc3RhdGVzAQwAYXR0YWNoZWRfYml0AAMJAGRpcmVjdGlvbgAAAAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:wooden_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRIAAAACAQAbmFtZR8AbWluZWNyYWZ0Ondvb2Rlbl9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaGkGs5kCuA74AwoAbmV0d29ya19pZDRzPNwKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:spruce_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSZAQAACAQAbmFtZR8AbWluZWNyYWZ0OnNwcnVjZV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaNmwuq549fJKAwoAbmV0d29ya19pZLQMCw0KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:birch_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSWAQAACAQAbmFtZR4AbWluZWNyYWZ0OmJpcmNoX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNorQkT9kDdlTwDCgBuZXR3b3JrX2lkH0G97AoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:jungle_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSYAQAACAQAbmFtZR8AbWluZWNyYWZ0Omp1bmdsZV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaJ7DcteCkb8/AwoAbmV0d29ya19pZLdPBSAKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:acacia_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSVAQAACAQAbmFtZR8AbWluZWNyYWZ0OmFjYWNpYV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaC2frZtfoYqCAwoAbmV0d29ya19pZIDdI18KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:dark_oak_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSXAQAACAQAbmFtZSEAbWluZWNyYWZ0OmRhcmtfb2FrX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoHUCJsTy52pwDCgBuZXR3b3JrX2lkKpi8rAoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:mangrove_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTpAgAACAQAbmFtZSEAbWluZWNyYWZ0Om1hbmdyb3ZlX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoiDsTfJaX100DCgBuZXR3b3JrX2lkuwWDyQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:cherry_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQZAwAACAQAbmFtZR8AbWluZWNyYWZ0OmNoZXJyeV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaALMqYEZDUQHAwoAbmV0d29ya19pZPNT+r0KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:bamboo_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAwAACAQAbmFtZR8AbWluZWNyYWZ0OmJhbWJvb19wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaNvxJ7NIAaqlAwoAbmV0d29ya19pZIZ8XnYKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:crimson_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQFAgAACAQAbmFtZSAAbWluZWNyYWZ0OmNyaW1zb25fcHJlc3N1cmVfcGxhdGUECQBuYW1lX2hhc2hqBDVDAd31/gMKAG5ldHdvcmtfaWRmV18LCgYAc3RhdGVzAw8AcmVkc3RvbmVfc2lnbmFsAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:warped_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAgAACAQAbmFtZR8AbWluZWNyYWZ0OndhcnBlZF9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaBxFoQksWtYUAwoAbmV0d29ya19pZJVRoIcKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:stone_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRGAAAACAQAbmFtZR4AbWluZWNyYWZ0OnN0b25lX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNounJuTBUTrU8DCgBuZXR3b3JrX2lkjDydwQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:light_weighted_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSTAAAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X3dlaWdodGVkX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoOyOJkNxLtkEDCgBuZXR3b3JrX2lkrr2AjgoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:heavy_weighted_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSUAAAACAQAbmFtZScAbWluZWNyYWZ0OmhlYXZ5X3dlaWdodGVkX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoltgDmDvTajUDCgBuZXR3b3JrX2lkFxVKuQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:polished_blackstone_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAgAACAQAbmFtZSwAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfcHJlc3N1cmVfcGxhdGUECQBuYW1lX2hhc2h65Ci6/CeGqwMKAG5ldHdvcmtfaWTaSW5xCgYAc3RhdGVzAw8AcmVkc3RvbmVfc2lnbmFsAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:observer", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT7AAAACAQAbmFtZRIAbWluZWNyYWZ0Om9ic2VydmVyBAkAbmFtZV9oYXNoYhlh1lpmHTgDCgBuZXR3b3JrX2lkQEh55goGAHN0YXRlcwgaAG1pbmVjcmFmdDpmYWNpbmdfZGlyZWN0aW9uBABkb3duAQsAcG93ZXJlZF9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:daylight_detector", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSXAAAACAQAbmFtZRsAbWluZWNyYWZ0OmRheWxpZ2h0X2RldGVjdG9yBAkAbmFtZV9oYXNoV0F0s7B7PVgDCgBuZXR3b3JrX2lkri5afQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:repeater" + }, + { + "id": "minecraft:comparator" + }, + { + "id": "minecraft:hopper" + }, + { + "id": "minecraft:dropper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR9AAAACAQAbmFtZREAbWluZWNyYWZ0OmRyb3BwZXIECQBuYW1lX2hhc2joXP7XqU0l3QMKAG5ldHdvcmtfaWQfQN6zCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgMAAAABDQB0cmlnZ2VyZWRfYml0AAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:dispenser", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQXAAAACAQAbmFtZRMAbWluZWNyYWZ0OmRpc3BlbnNlcgQJAG5hbWVfaGFzaP1RR+zAbYP2AwoAbmV0d29ya19pZGAayD0KBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAwAAAAENAHRyaWdnZXJlZF9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:crafter", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ4AgAACAQAbmFtZREAbWluZWNyYWZ0OmNyYWZ0ZXIECQBuYW1lX2hhc2iLCT/rJmRN8QMKAG5ldHdvcmtfaWTPTbvrCgYAc3RhdGVzAQgAY3JhZnRpbmcACAsAb3JpZW50YXRpb24JAGRvd25fZWFzdAENAHRyaWdnZXJlZF9iaXQAAAMHAHZlcnNpb24GFBUBAA==" + }, + { + "id": "minecraft:piston", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQhAAAACAQAbmFtZRAAbWluZWNyYWZ0OnBpc3RvbgQJAG5hbWVfaGFzaDs3AFh1fL0uAwoAbmV0d29ya19pZLD/5XQKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAQAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:sticky_piston", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQdAAAACAQAbmFtZRcAbWluZWNyYWZ0OnN0aWNreV9waXN0b24ECQBuYW1lX2hhc2hPFJFJSiJ0ZQMKAG5ldHdvcmtfaWT/MzCJCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgEAAAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:tnt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQuAAAACAQAbmFtZQ0AbWluZWNyYWZ0OnRudAQJAG5hbWVfaGFzaEYOHwCvJH29AwoAbmV0d29ya19pZCGfjU4KBgBzdGF0ZXMBFABhbGxvd191bmRlcndhdGVyX2JpdAABCwBleHBsb2RlX2JpdAAAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:name_tag" + }, + { + "id": "minecraft:loom", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAQAACAQAbmFtZQ4AbWluZWNyYWZ0Omxvb20ECQBuYW1lX2hhc2i7DKjAXNq8TAMKAG5ldHdvcmtfaWR/49HXCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:banner", + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 8, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 7, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 15, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 12, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 14, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 1, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 4, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 5, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 13, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 9, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 3, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 11, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 10, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 2, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 6, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 15, + "nbt_b64": "CgAAAwQAVHlwZQEAAAAA" + }, + { + "id": "minecraft:creeper_banner_pattern" + }, + { + "id": "minecraft:skull_banner_pattern" + }, + { + "id": "minecraft:flower_banner_pattern" + }, + { + "id": "minecraft:mojang_banner_pattern" + }, + { + "id": "minecraft:field_masoned_banner_pattern" + }, + { + "id": "minecraft:bordure_indented_banner_pattern" + }, + { + "id": "minecraft:piglin_banner_pattern" + }, + { + "id": "minecraft:globe_banner_pattern" + }, + { + "id": "minecraft:flow_banner_pattern" + }, + { + "id": "minecraft:guster_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:flow_pottery_sherd" + }, + { + "id": "minecraft:friend_pottery_sherd" + }, + { + "id": "minecraft:guster_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:scrape_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:flow_armor_trim_smithing_template" + }, + { + "id": "minecraft:bolt_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": "CgAAAwgAYmxvY2tfaWTuAQAACAQAbmFtZRAAbWluZWNyYWZ0OnRhcmdldAQJAG5hbWVfaGFzaJc66SVbYlaxAwoAbmV0d29ya19pZPBozs0KBgBzdGF0ZXMAAwcAdmVyc2lvbgYUFQEA" + }, + { + "id": "minecraft:decorated_pot", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAwAACAQAbmFtZRcAbWluZWNyYWZ0OmRlY29yYXRlZF9wb3QECQBuYW1lX2hhc2jjQgckn8VTvwMKAG5ldHdvcmtfaWRwvkUUCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBhQVAQA=" + }, + { + "id": "minecraft:lodestone_compass" + }, + { + "id": "minecraft:wither_spawn_egg" + }, + { + "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/creative_items.1_21_30.json b/core/src/main/resources/bedrock/creative_items.1_21_30.json new file mode 100644 index 000000000..8fab4638e --- /dev/null +++ b/core/src/main/resources/bedrock/creative_items.1_21_30.json @@ -0,0 +1,6214 @@ +{ + "items": [ + { + "id": "minecraft:oak_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQFAAAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19wbGFua3MECQBuYW1lX2hhc2ilMDLR92rQ4wMKAG5ldHdvcmtfaWS2GotyCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:spruce_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAwAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9wbGFua3MECQBuYW1lX2hhc2iumBkmFGFE8gMKAG5ldHdvcmtfaWSo8TFgCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:birch_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX3BsYW5rcwQJAG5hbWVfaGFzaLrrAKJqV2WFAwoAbmV0d29ya19pZL+e3ZAKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:jungle_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAwAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9wbGFua3MECQBuYW1lX2hhc2iBM3k4T3FAugMKAG5ldHdvcmtfaWSXUmBCCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:acacia_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAwAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9wbGFua3MECQBuYW1lX2hhc2g60edJxO5/aAMKAG5ldHdvcmtfaWTUXozECgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:dark_oak_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTmAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX3BsYW5rcwQJAG5hbWVfaGFzaAr64wkQ9cA7AwoAbmV0d29ya19pZFbMeR0KBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:mangrove_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX3BsYW5rcwQJAG5hbWVfaGFzaPvLtcEA0F8xAwoAbmV0d29ya19pZEvnlCYKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:cherry_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9wbGFua3MECQBuYW1lX2hhc2hNIvVh/lVW7gMKAG5ldHdvcmtfaWQTXpRoCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:bamboo_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT9AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19wbGFua3MECQBuYW1lX2hhc2gYnjNz7SCCjgMKAG5ldHdvcmtfaWTi8ySSCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:bamboo_mosaic", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT8AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19tb3NhaWMECQBuYW1lX2hhc2izSEgiMKOp/AMKAG5ldHdvcmtfaWQZ/p8xCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:crimson_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTxAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fcGxhbmtzBAkAbmFtZV9oYXNoJc5IKqNXJnwDCgBuZXR3b3JrX2lkwtJDdQoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:warped_planks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTyAQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9wbGFua3MECQBuYW1lX2hhc2g3yGXEWhe6LgMKAG5ldHdvcmtfaWStTABvCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2hZu/xE7lYtNgMKAG5ldHdvcmtfaWSLY2XwCgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:mossy_cobblestone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTKBAAACAQAbmFtZSAAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lX3dhbGwECQBuYW1lX2hhc2gHUQMwwFQeNQMKAG5ldHdvcmtfaWRzPhG8CgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:granite_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTLBAAACAQAbmFtZRYAbWluZWNyYWZ0OmdyYW5pdGVfd2FsbAQJAG5hbWVfaGFzaE1GmM5AU0qUAwoAbmV0d29ya19pZE/UoPUKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:diorite_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTMBAAACAQAbmFtZRYAbWluZWNyYWZ0OmRpb3JpdGVfd2FsbAQJAG5hbWVfaGFzaF27l0QvdM8xAwoAbmV0d29ya19pZJe7jOwKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:andesite_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTNBAAACAQAbmFtZRcAbWluZWNyYWZ0OmFuZGVzaXRlX3dhbGwECQBuYW1lX2hhc2gAL1Vay0kZjQMKAG5ldHdvcmtfaWRJGxdvCgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:sandstone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTOBAAACAQAbmFtZRgAbWluZWNyYWZ0OnNhbmRzdG9uZV93YWxsBAkAbmFtZV9oYXNoYL2gu8a6HfgDCgBuZXR3b3JrX2lkHrhRjgoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:red_sandstone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTVBAAACAQAbmFtZRwAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmVfd2FsbAQJAG5hbWVfaGFzaLAUUdOlo24MAwoAbmV0d29ya19pZI66BqAKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:stone_brick_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTQBAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2JyaWNrX3dhbGwECQBuYW1lX2hhc2hQegufuP6vjAMKAG5ldHdvcmtfaWS4AsOKCgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:mossy_stone_brick_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTRBAAACAQAbmFtZSAAbWluZWNyYWZ0Om1vc3N5X3N0b25lX2JyaWNrX3dhbGwECQBuYW1lX2hhc2i680zzUekp+wMKAG5ldHdvcmtfaWTQTaHPCgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:brick_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTPBAAACAQAbmFtZRQAbWluZWNyYWZ0OmJyaWNrX3dhbGwECQBuYW1lX2hhc2gGJFLNjfgSCAMKAG5ldHdvcmtfaWSc5iUZCgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:nether_brick_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTSBAAACAQAbmFtZRsAbWluZWNyYWZ0Om5ldGhlcl9icmlja193YWxsBAkAbmFtZV9oYXNoAxb5f2yQ5MYDCgBuZXR3b3JrX2lkAECPDAoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:red_nether_brick_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTWBAAACAQAbmFtZR8AbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2tfd2FsbAQJAG5hbWVfaGFzaBOtwkokUt3cAwoAbmV0d29ya19pZJykmZUKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:end_stone_brick_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTBAAACAQAbmFtZR4AbWluZWNyYWZ0OmVuZF9zdG9uZV9icmlja193YWxsBAkAbmFtZV9oYXNoOsr1L9kJIAMDCgBuZXR3b3JrX2lkjuYlYgoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:prismarine_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTUBAAACAQAbmFtZRkAbWluZWNyYWZ0OnByaXNtYXJpbmVfd2FsbAQJAG5hbWVfaGFzaDO5IGrYZu1/AwoAbmV0d29ya19pZB4nLYYKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:blackstone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQUAgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsYWNrc3RvbmVfd2FsbAQJAG5hbWVfaGFzaMP8XppUSU1RAwoAbmV0d29ya19pZMbeBBsKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:polished_blackstone_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQoAgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfd2FsbAQJAG5hbWVfaGFzaP6SwV08YwzAAwoAbmV0d29ya19pZAJLsz8KBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:polished_blackstone_brick_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQVAgAACAQAbmFtZSgAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfd2FsbAQJAG5hbWVfaGFzaBBIDZbHxiEzAwoAbmV0d29ya19pZEbLV8cKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:cobbled_deepslate_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR9AgAACAQAbmFtZSAAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3dhbGwECQBuYW1lX2hhc2iECY5oKxeT+gMKAG5ldHdvcmtfaWRCnPrFCgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:deepslate_tile_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3dhbGwECQBuYW1lX2hhc2jz7N+PeuEXgQMKAG5ldHdvcmtfaWTqw4s4CgYAc3RhdGVzCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfZWFzdAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX25vcnRoBABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfc291dGgEAG5vbmUIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV93ZXN0BABub25lAQ0Ad2FsbF9wb3N0X2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:polished_deepslate_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV93YWxsBAkAbmFtZV9oYXNoHxjTdj9pevMDCgBuZXR3b3JrX2lkIvBYYwoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:deepslate_brick_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSJAgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja193YWxsBAkAbmFtZV9oYXNoEs3EQrjroyEDCgBuZXR3b3JrX2lkwlrCGwoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:mud_brick_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAgAACAQAbmFtZRgAbWluZWNyYWZ0Om11ZF9icmlja193YWxsBAkAbmFtZV9oYXNov9b98ATpUSwDCgBuZXR3b3JrX2lkH/1WZQoGAHN0YXRlcwgZAHdhbGxfY29ubmVjdGlvbl90eXBlX2Vhc3QEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9ub3J0aAQAbm9uZQgaAHdhbGxfY29ubmVjdGlvbl90eXBlX3NvdXRoBABub25lCBkAd2FsbF9jb25uZWN0aW9uX3R5cGVfd2VzdAQAbm9uZQENAHdhbGxfcG9zdF9iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:oak_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRVAAAACAQAbmFtZRMAbWluZWNyYWZ0Om9ha19mZW5jZQQJAG5hbWVfaGFzaGEmid7AaCWRAwoAbmV0d29ya19pZDvPEXcKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:spruce_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRCAwAACAQAbmFtZRYAbWluZWNyYWZ0OnNwcnVjZV9mZW5jZQQJAG5hbWVfaGFzaPQCm+aX1ZQeAwoAbmV0d29ya19pZD1QUEoKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:birch_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ/AwAACAQAbmFtZRUAbWluZWNyYWZ0OmJpcmNoX2ZlbmNlBAkAbmFtZV9oYXNo6CJ2ATpANfgDCgBuZXR3b3JrX2lkmCUV2QoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:jungle_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRBAwAACAQAbmFtZRYAbWluZWNyYWZ0Omp1bmdsZV9mZW5jZQQJAG5hbWVfaGFzaOX4cD9uAmsdAwoAbmV0d29ya19pZHz1VxkKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:acacia_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ+AwAACAQAbmFtZRYAbWluZWNyYWZ0OmFjYWNpYV9mZW5jZQQJAG5hbWVfaGFzaGjn+RlKVDH6AwoAbmV0d29ya19pZNVGubwKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:dark_oak_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRAAwAACAQAbmFtZRgAbWluZWNyYWZ0OmRhcmtfb2FrX2ZlbmNlBAkAbmFtZV9oYXNoGPj0gCgM0c0DCgBuZXR3b3JrX2lk2w+gEwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:mangrove_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTqAgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hbmdyb3ZlX2ZlbmNlBAkAbmFtZV9oYXNowwAd7tPu9bsDCgBuZXR3b3JrX2lkKEcd0goGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:cherry_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAwAACAQAbmFtZRYAbWluZWNyYWZ0OmNoZXJyeV9mZW5jZQQJAG5hbWVfaGFzaFmtUfHfTxcxAwoAbmV0d29ya19pZPCBxAIKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:bamboo_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJhbWJvb19mZW5jZQQJAG5hbWVfaGFzaCKRbxfXsfkiAwoAbmV0d29ya19pZJNXKFcKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:nether_brick_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRxAAAACAQAbmFtZRwAbWluZWNyYWZ0Om5ldGhlcl9icmlja19mZW5jZQQJAG5hbWVfaGFzaA6030ngawxcAwoAbmV0d29ya19pZLnjLF4KBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:crimson_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT/AQAACAQAbmFtZRcAbWluZWNyYWZ0OmNyaW1zb25fZmVuY2UECQBuYW1lX2hhc2jhUhKv1HGj9AMKAG5ldHdvcmtfaWR3OH3OCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:warped_fence", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQAAgAACAQAbmFtZRYAbWluZWNyYWZ0OndhcnBlZF9mZW5jZQQJAG5hbWVfaGFzaJfb3/YuKmOWAwoAbmV0d29ya19pZCpaGC8KBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRrAAAACAQAbmFtZRQAbWluZWNyYWZ0OmZlbmNlX2dhdGUECQBuYW1lX2hhc2hTxpjEDmRzAwMKAG5ldHdvcmtfaWR+T9kTCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:spruce_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS3AAAACAQAbmFtZRsAbWluZWNyYWZ0OnNwcnVjZV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoanTVB84HRbkDCgBuZXR3b3JrX2lkEnw5egoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:birch_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS4AAAACAQAbmFtZRoAbWluZWNyYWZ0OmJpcmNoX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2jmfPklI8azSwMKAG5ldHdvcmtfaWQL77/BCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:jungle_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS5AAAACAQAbmFtZRsAbWluZWNyYWZ0Omp1bmdsZV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNobYVQkfBomIcDCgBuZXR3b3JrX2lkA1zgtgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:acacia_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS7AAAACAQAbmFtZRsAbWluZWNyYWZ0OmFjYWNpYV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoZnrLUx/XSekDCgBuZXR3b3JrX2lkHg/kTgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:dark_oak_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS6AAAACAQAbmFtZR0AbWluZWNyYWZ0OmRhcmtfb2FrX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2j2PTvdJJHcVQMKAG5ldHdvcmtfaWTwjOCeCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:mangrove_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTrAgAACAQAbmFtZR0AbWluZWNyYWZ0Om1hbmdyb3ZlX2ZlbmNlX2dhdGUECQBuYW1lX2hhc2i/kOhBKiI/dAMKAG5ldHdvcmtfaWSfweCSCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAELAGluX3dhbGxfYml0AAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:cherry_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQUAwAACAQAbmFtZRsAbWluZWNyYWZ0OmNoZXJyeV9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoKWLgCk0z+PsDCgBuZXR3b3JrX2lk/9bTZQoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:bamboo_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAwAACAQAbmFtZRsAbWluZWNyYWZ0OmJhbWJvb19mZW5jZV9nYXRlBAkAbmFtZV9oYXNopH1JrUgwdIADCgBuZXR3b3JrX2lkzIpPywoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:crimson_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAgAACAQAbmFtZRwAbWluZWNyYWZ0OmNyaW1zb25fZmVuY2VfZ2F0ZQQJAG5hbWVfaGFzaHE3Gfd0Z2d2AwoAbmV0d29ya19pZDQzVbEKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQsAaW5fd2FsbF9iaXQAAQgAb3Blbl9iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:warped_fence_gate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAgAACAQAbmFtZRsAbWluZWNyYWZ0OndhcnBlZF9mZW5jZV9nYXRlBAkAbmFtZV9oYXNoy0oIBjDIG4kDCgBuZXR3b3JrX2lkkf+/3QoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCwBpbl93YWxsX2JpdAABCABvcGVuX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:normal_stone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAQAACAQAbmFtZR0AbWluZWNyYWZ0Om5vcm1hbF9zdG9uZV9zdGFpcnMECQBuYW1lX2hhc2hAEktZZOkGIwMKAG5ldHdvcmtfaWQeH1ALCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:stone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRDAAAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX3N0YWlycwQJAG5hbWVfaGFzaNRjqVC5GRVDAwoAbmV0d29ya19pZDcCv+MKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:mossy_cobblestone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSyAQAACAQAbmFtZSIAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lX3N0YWlycwQJAG5hbWVfaGFzaMVSTq5z9n1RAwoAbmV0d29ya19pZFIfrhkKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:oak_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ1AAAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19zdGFpcnMECQBuYW1lX2hhc2jk/HFzdXy0FQMKAG5ldHdvcmtfaWQJjyzBCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:spruce_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSGAAAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9zdGFpcnMECQBuYW1lX2hhc2iznygw7uBPBQMKAG5ldHdvcmtfaWTv+is3CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:birch_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSHAAAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX3N0YWlycwQJAG5hbWVfaGFzaPfhbL619a3GAwoAbmV0d29ya19pZFyPlHAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:jungle_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSIAAAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9zdGFpcnMECQBuYW1lX2hhc2jodJsHUbOVxQMKAG5ldHdvcmtfaWR0z5d4CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:acacia_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSjAAAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9zdGFpcnMECQBuYW1lX2hhc2h3x1NmD43IqQMKAG5ldHdvcmtfaWS7Jwz6CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:dark_oak_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAAAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX3N0YWlycwQJAG5hbWVfaGFzaMfwkbYPbNmAAwoAbmV0d29ya19pZCmBYKAKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:mangrove_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTnAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX3N0YWlycwQJAG5hbWVfaGFzaNpUDY+uGMpyAwoAbmV0d29ya19pZChzUAsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:cherry_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQcAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9zdGFpcnMECQBuYW1lX2hhc2jMtr0v9JY4zwMKAG5ldHdvcmtfaWRQwq31CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:bamboo_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT/AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19zdGFpcnMECQBuYW1lX2hhc2jFOzWL8PalKwMKAG5ldHdvcmtfaWTVPh42CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:bamboo_mosaic_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQKAwAACAQAbmFtZR4AbWluZWNyYWZ0OmJhbWJvb19tb3NhaWNfc3RhaXJzBAkAbmFtZV9oYXNoNLPiveSHPaoDCgBuZXR3b3JrX2lk44PHjgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:stone_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRtAAAACAQAbmFtZRwAbWluZWNyYWZ0OnN0b25lX2JyaWNrX3N0YWlycwQJAG5hbWVfaGFzaN6tQViRo5cwAwoAbmV0d29ya19pZDMyMgIKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:mossy_stone_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSuAQAACAQAbmFtZSIAbWluZWNyYWZ0Om1vc3N5X3N0b25lX2JyaWNrX3N0YWlycwQJAG5hbWVfaGFzaIB/Zv5YBPuYAwoAbmV0d29ya19pZANTOsMKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:sandstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSAAAAACAQAbmFtZRoAbWluZWNyYWZ0OnNhbmRzdG9uZV9zdGFpcnMECQBuYW1lX2hhc2hOyA0BoYUOPQMKAG5ldHdvcmtfaWSV/834CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:smooth_sandstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSwAQAACAQAbmFtZSEAbWluZWNyYWZ0OnNtb290aF9zYW5kc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNoB+CuCd8Ruz8DCgBuZXR3b3JrX2lksR+m8QoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:red_sandstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS0AAAACAQAbmFtZR4AbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNoPs0LpHPL24YDCgBuZXR3b3JrX2lkLYVt3woGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:smooth_red_sandstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAQAACAQAbmFtZSUAbWluZWNyYWZ0OnNtb290aF9yZWRfc2FuZHN0b25lX3N0YWlycwQJAG5hbWVfaGFzaBvjtQv5pf+MAwoAbmV0d29ya19pZMHNND8KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:granite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAQAACAQAbmFtZRgAbWluZWNyYWZ0OmdyYW5pdGVfc3RhaXJzBAkAbmFtZV9oYXNoGzpvtoqKQjgDCgBuZXR3b3JrX2lkPkcB1goGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:polished_granite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAQAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2dyYW5pdGVfc3RhaXJzBAkAbmFtZV9oYXNo3PvbSfEQklIDCgBuZXR3b3JrX2lkMmEm3AoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:diorite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAQAACAQAbmFtZRgAbWluZWNyYWZ0OmRpb3JpdGVfc3RhaXJzBAkAbmFtZV9oYXNoi73T8VQuZmcDCgBuZXR3b3JrX2lk6i6nBQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:polished_diorite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSsAQAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2Rpb3JpdGVfc3RhaXJzBAkAbmFtZV9oYXNoFKRJd5Wk5L0DCgBuZXR3b3JrX2lkbt2ioAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:andesite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAQAACAQAbmFtZRkAbWluZWNyYWZ0OmFuZGVzaXRlX3N0YWlycwQJAG5hbWVfaGFzaO5w2FKBw76EAwoAbmV0d29ya19pZKhXEgUKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:polished_andesite_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWStAQAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2FuZGVzaXRlX3N0YWlycwQJAG5hbWVfaGFzaNcZZ/zmLInIAwoAbmV0d29ya19pZJTHrlEKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRsAAAACAQAbmFtZRYAbWluZWNyYWZ0OmJyaWNrX3N0YWlycwQJAG5hbWVfaGFzaMyt+cRDk5O2AwoAbmV0d29ya19pZNeMh58KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:nether_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRyAAAACAQAbmFtZR0AbWluZWNyYWZ0Om5ldGhlcl9icmlja19zdGFpcnMECQBuYW1lX2hhc2jRqIoOXgifBAMKAG5ldHdvcmtfaWQDiw5yCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:red_nether_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS3AQAACAQAbmFtZSEAbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNogQvosSbcj7kDCgBuZXR3b3JrX2lkx2IMtAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:end_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSxAQAACAQAbmFtZRoAbWluZWNyYWZ0OmVuZF9icmlja19zdGFpcnMECQBuYW1lX2hhc2hmlAk+QhsUsQMKAG5ldHdvcmtfaWTN7KFaCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:quartz_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWScAAAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9zdGFpcnMECQBuYW1lX2hhc2hmvpvOqGi6egMKAG5ldHdvcmtfaWRmUTh7CgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:smooth_quartz_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS4AQAACAQAbmFtZR4AbWluZWNyYWZ0OnNtb290aF9xdWFydHpfc3RhaXJzBAkAbmFtZV9oYXNoNZZ9rX0qZOsDCgBuZXR3b3JrX2lkzsgQyQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:purpur_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAAAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnB1cl9zdGFpcnMECQBuYW1lX2hhc2ifwDxeezXD7gMKAG5ldHdvcmtfaWTT+rxiCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:prismarine_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAQAACAQAbmFtZRsAbWluZWNyYWZ0OnByaXNtYXJpbmVfc3RhaXJzBAkAbmFtZV9oYXNooTHSZ+IrYtcDCgBuZXR3b3JrX2lkxTJfeAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:dark_prismarine_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAQAACAQAbmFtZSAAbWluZWNyYWZ0OmRhcmtfcHJpc21hcmluZV9zdGFpcnMECQBuYW1lX2hhc2hIciLmam4o4AMKAG5ldHdvcmtfaWTVu7TCCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:prismarine_bricks_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAQAACAQAbmFtZSIAbWluZWNyYWZ0OnByaXNtYXJpbmVfYnJpY2tzX3N0YWlycwQJAG5hbWVfaGFzaNIjq1oBlZMMAwoAbmV0d29ya19pZGEFwLYKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:crimson_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT9AQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fc3RhaXJzBAkAbmFtZV9oYXNoZJqIzCBpCq4DCgBuZXR3b3JrX2lktXE00AoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:warped_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT+AQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9zdGFpcnMECQBuYW1lX2hhc2hOkY27jLD4RQMKAG5ldHdvcmtfaWQ+E5VrCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:blackstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAgAACAQAbmFtZRsAbWluZWNyYWZ0OmJsYWNrc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNokdoUb76p9McDCgBuZXR3b3JrX2lk5fWI5goGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:polished_blackstone_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQjAgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfc3RhaXJzBAkAbmFtZV9oYXNolCFtFIE8MmADCgBuZXR3b3JrX2lkGTf7sgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:polished_blackstone_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQSAgAACAQAbmFtZSoAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNonks6UlfpOmkDCgBuZXR3b3JrX2lkgYeOdAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAgAACAQAbmFtZRsAbWluZWNyYWZ0OmN1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoHfoAXYq5G3MDCgBuZXR3b3JrX2lkeetf7woGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:exposed_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAgAACAQAbmFtZSMAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcl9zdGFpcnMECQBuYW1lX2hhc2howneQGtZ9cgMKAG5ldHdvcmtfaWSg73zdCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:weathered_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAgAACAQAbmFtZSUAbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyX3N0YWlycwQJAG5hbWVfaGFzaP+R5loXxrVgAwoAbmV0d29ya19pZOnbRf4KBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:oxidized_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRkAgAACAQAbmFtZSQAbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNo6Jeoq5rsPxsDCgBuZXR3b3JrX2lkmRjDnQoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:waxed_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRlAgAACAQAbmFtZSEAbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoh07CQj0/SR8DCgBuZXR3b3JrX2lkmYqoqAoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:waxed_exposed_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRmAgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcl9zdGFpcnMECQBuYW1lX2hhc2guVct1ilmxTwMKAG5ldHdvcmtfaWQgCPROCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:waxed_weathered_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRnAgAACAQAbmFtZSsAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyX3N0YWlycwQJAG5hbWVfaGFzaPXC8Sz/phCpAwoAbmV0d29ya19pZHlwHVsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:waxed_oxidized_cut_copper_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS/AgAACAQAbmFtZSoAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXJfc3RhaXJzBAkAbmFtZV9oYXNoaqGdkuhxVZUDCgBuZXR3b3JrX2lkYQXzzgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:cobbled_deepslate_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR8AgAACAQAbmFtZSIAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3N0YWlycwQJAG5hbWVfaGFzaPIfa+TpyJcIAwoAbmV0d29ya19pZJUvOYIKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:deepslate_tile_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3N0YWlycwQJAG5hbWVfaGFzaGFRFzB72mN2AwoAbmV0d29ya19pZJEOgIsKBgBzdGF0ZXMBDwB1cHNpZGVfZG93bl9iaXQAAxAAd2VpcmRvX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:polished_deepslate_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSAAgAACAQAbmFtZSMAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV9zdGFpcnMECQBuYW1lX2hhc2iNCYxVik9sGAMKAG5ldHdvcmtfaWSRVPnYCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:deepslate_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSIAgAACAQAbmFtZSAAbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja19zdGFpcnMECQBuYW1lX2hhc2hIasOahEf83wMKAG5ldHdvcmtfaWQ1qEDCCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:mud_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAgAACAQAbmFtZRoAbWluZWNyYWZ0Om11ZF9icmlja19zdGFpcnMECQBuYW1lX2hhc2gt3qxK1NWajAMKAG5ldHdvcmtfaWSm9N3MCgYAc3RhdGVzAQ8AdXBzaWRlX2Rvd25fYml0AAMQAHdlaXJkb19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "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": "CgAAAwgAYmxvY2tfaWRgAAAACAQAbmFtZRIAbWluZWNyYWZ0OnRyYXBkb29yBAkAbmFtZV9oYXNotYiAJGtN0xADCgBuZXR3b3JrX2lkyTAWkAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:spruce_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSUAQAACAQAbmFtZRkAbWluZWNyYWZ0OnNwcnVjZV90cmFwZG9vcgQJAG5hbWVfaGFzaOwlfbgBkUW4AwoAbmV0d29ya19pZPHy1K0KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:birch_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAQAACAQAbmFtZRgAbWluZWNyYWZ0OmJpcmNoX3RyYXBkb29yBAkAbmFtZV9oYXNoSLtLweOLJ7wDCgBuZXR3b3JrX2lkeJWDfgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:jungle_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSTAQAACAQAbmFtZRkAbWluZWNyYWZ0Omp1bmdsZV90cmFwZG9vcgQJAG5hbWVfaGFzaDP/TnM9wyCIAwoAbmV0d29ya19pZEy2fJoKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:acacia_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSQAQAACAQAbmFtZRkAbWluZWNyYWZ0OmFjYWNpYV90cmFwZG9vcgQJAG5hbWVfaGFzaMj8xi3vmEKOAwoAbmV0d29ya19pZOHj8E8KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:dark_oak_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSSAQAACAQAbmFtZRsAbWluZWNyYWZ0OmRhcmtfb2FrX3RyYXBkb29yBAkAbmFtZV9oYXNomB2GGJQ2aOMDCgBuZXR3b3JrX2lko5ZHTwoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:mangrove_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTvAgAACAQAbmFtZRsAbWluZWNyYWZ0Om1hbmdyb3ZlX3RyYXBkb29yBAkAbmFtZV9oYXNooV3kQsQUUmkDCgBuZXR3b3JrX2lkkF/mxAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:cherry_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQeAwAACAQAbmFtZRkAbWluZWNyYWZ0OmNoZXJyeV90cmFwZG9vcgQJAG5hbWVfaGFzaH/PefpfdHgtAwoAbmV0d29ya19pZOA7eNgKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:bamboo_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAwAACAQAbmFtZRkAbWluZWNyYWZ0OmJhbWJvb190cmFwZG9vcgQJAG5hbWVfaGFzaJrEOpsTwtKCAwoAbmV0d29ya19pZLvbPz8KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:iron_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSnAAAACAQAbmFtZRcAbWluZWNyYWZ0Omlyb25fdHJhcGRvb3IECQBuYW1lX2hhc2gwA+IumsEiGQMKAG5ldHdvcmtfaWTvSVl/CgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:crimson_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT1AQAACAQAbmFtZRoAbWluZWNyYWZ0OmNyaW1zb25fdHJhcGRvb3IECQBuYW1lX2hhc2jHXufTnwUkYgMKAG5ldHdvcmtfaWQLjMYVCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:warped_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT2AQAACAQAbmFtZRkAbWluZWNyYWZ0OndhcnBlZF90cmFwZG9vcgQJAG5hbWVfaGFzaA20wG/+vkd6AwoAbmV0d29ya19pZHKR/hYKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:iron_bars", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRlAAAACAQAbmFtZRMAbWluZWNyYWZ0Omlyb25fYmFycwQJAG5hbWVfaGFzaPuefWSNAe56AwoAbmV0d29ya19pZN2LB5IKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQUAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmdsYXNzBAkAbmFtZV9oYXNowGJByfWff6gDCgBuZXR3b3JrX2lk0hdLNwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:white_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTxAAAACAQAbmFtZR0AbWluZWNyYWZ0OndoaXRlX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2iHubqoMbu9fAMKAG5ldHdvcmtfaWRndBrUCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:light_gray_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSnAwAACAQAbmFtZSIAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaKKa+LrRsHQhAwoAbmV0d29ya19pZEv2giYKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:gray_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSmAwAACAQAbmFtZRwAbWluZWNyYWZ0OmdyYXlfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaIETy7Y/HZREAwoAbmV0d29ya19pZDomVrUKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:black_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSuAwAACAQAbmFtZR0AbWluZWNyYWZ0OmJsYWNrX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2iV6BCwpfDMmwMKAG5ldHdvcmtfaWSV7doJCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:brown_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAwAACAQAbmFtZR0AbWluZWNyYWZ0OmJyb3duX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2igsEiq5np8JgMKAG5ldHdvcmtfaWRMzE/lCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:red_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWStAwAACAQAbmFtZRsAbWluZWNyYWZ0OnJlZF9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNoCa2J12/lQoIDCgBuZXR3b3JrX2lk283lWAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:orange_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSgAwAACAQAbmFtZR4AbWluZWNyYWZ0Om9yYW5nZV9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNozgjAuvzhxGsDCgBuZXR3b3JrX2lkW5CkhQoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:yellow_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSjAwAACAQAbmFtZR4AbWluZWNyYWZ0OnllbGxvd19zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNo7EbHMd5WVugDCgBuZXR3b3JrX2lkkdDyXQoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:lime_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAwAACAQAbmFtZRwAbWluZWNyYWZ0OmxpbWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaBtZA1nZtwcFAwoAbmV0d29ya19pZDxX85UKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:green_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSsAwAACAQAbmFtZR0AbWluZWNyYWZ0OmdyZWVuX3N0YWluZWRfZ2xhc3MECQBuYW1lX2hhc2h91ptDgbehWwMKAG5ldHdvcmtfaWTlDhnECgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:cyan_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAwAACAQAbmFtZRwAbWluZWNyYWZ0OmN5YW5fc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaBkIYQ8nQLqbAwoAbmV0d29ya19pZOL1lHsKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:light_blue_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAwAACAQAbmFtZSIAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaLt05n1G0fiSAwoAbmV0d29ya19pZNbwulIKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:blue_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAwAACAQAbmFtZRwAbWluZWNyYWZ0OmJsdWVfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaPhLocSfzduRAwoAbmV0d29ya19pZENsjFwKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:purple_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAwAACAQAbmFtZR4AbWluZWNyYWZ0OnB1cnBsZV9zdGFpbmVkX2dsYXNzBAkAbmFtZV9oYXNoJk0DhRO0szUDCgBuZXR3b3JrX2lkD98ZxgoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:magenta_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAwAACAQAbmFtZR8AbWluZWNyYWZ0Om1hZ2VudGFfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaFEDeFiJj3zSAwoAbmV0d29ya19pZG+iFRoKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:pink_stained_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAwAACAQAbmFtZRwAbWluZWNyYWZ0OnBpbmtfc3RhaW5lZF9nbGFzcwQJAG5hbWVfaGFzaDijTX87ywxhAwoAbmV0d29ya19pZKdEricKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:tinted_glass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRNAgAACAQAbmFtZRYAbWluZWNyYWZ0OnRpbnRlZF9nbGFzcwQJAG5hbWVfaGFzaAFZWSamk6KdAwoAbmV0d29ya19pZGSvWX8KBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRmAAAACAQAbmFtZRQAbWluZWNyYWZ0OmdsYXNzX3BhbmUECQBuYW1lX2hhc2gRSBHwNMQ4gQMKAG5ldHdvcmtfaWRGwixuCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:white_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSgAAAACAQAbmFtZSIAbWluZWNyYWZ0OndoaXRlX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaHgxQmgJVtRrAwoAbmV0d29ya19pZBEr/DYKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:light_gray_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSJAwAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNon0aQw9lNkSEDCgBuZXR3b3JrX2lk9dp5VgoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:gray_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSIAwAACAQAbmFtZSEAbWluZWNyYWZ0OmdyYXlfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNors74IIw+2MMDCgBuZXR3b3JrX2lkmrGO5woGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:black_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSQAwAACAQAbmFtZSIAbWluZWNyYWZ0OmJsYWNrX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaOK/5ZRRd+M1AwoAbmV0d29ya19pZDv++oQKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:brown_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSNAwAACAQAbmFtZSIAbWluZWNyYWZ0OmJyb3duX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaLHeGJyRFTIWAwoAbmV0d29ya19pZMz9L0wKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:red_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAwAACAQAbmFtZSAAbWluZWNyYWZ0OnJlZF9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2gGr4x6JheAywMKAG5ldHdvcmtfaWQBjCTmCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:orange_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAwAACAQAbmFtZSMAbWluZWNyYWZ0Om9yYW5nZV9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2hbHxPD2gEbEAMKAG5ldHdvcmtfaWSt/7a5CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:yellow_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAwAACAQAbmFtZSMAbWluZWNyYWZ0OnllbGxvd19zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2g9tl4aOCyZBwMKAG5ldHdvcmtfaWTXRAS7CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:lime_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSGAwAACAQAbmFtZSEAbWluZWNyYWZ0OmxpbWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNo3CtUyLwoGegDCgBuZXR3b3JrX2lkYJDnggoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:green_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSOAwAACAQAbmFtZSIAbWluZWNyYWZ0OmdyZWVuX3N0YWluZWRfZ2xhc3NfcGFuZQQJAG5hbWVfaGFzaJo6YP7IMy9SAwoAbmV0d29ya19pZHOnixoKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:cyan_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAwAACAQAbmFtZSEAbWluZWNyYWZ0OmN5YW5fc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoti97c6QrbLQDCgBuZXR3b3JrX2lkUqFUeQoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:light_blue_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAwAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNovDg/gQle104DCgBuZXR3b3JrX2lkFuy4MQoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:blue_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSMAwAACAQAbmFtZSEAbWluZWNyYWZ0OmJsdWVfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoGc57tiexbQMDCgBuZXR3b3JrX2lk1eBLUAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:purple_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAwAACAQAbmFtZSMAbWluZWNyYWZ0OnB1cnBsZV9zdGFpbmVkX2dsYXNzX3BhbmUECQBuYW1lX2hhc2hDJHYdd0FdfQMKAG5ldHdvcmtfaWSNsdK5CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:magenta_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAwAACAQAbmFtZSQAbWluZWNyYWZ0Om1hZ2VudGFfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNo3pcOw5bs5XoDCgBuZXR3b3JrX2lkVbOR7AoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:pink_stained_glass_pane", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSHAwAACAQAbmFtZSEAbWluZWNyYWZ0OnBpbmtfc3RhaW5lZF9nbGFzc19wYW5lBAkAbmFtZV9oYXNoWRhSACMWgswDCgBuZXR3b3JrX2lkIR92xwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:ladder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRBAAAACAQAbmFtZRAAbWluZWNyYWZ0OmxhZGRlcgQJAG5hbWVfaGFzaKBhqheJVOz+AwoAbmV0d29ya19pZCgvzlsKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:scaffolding", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAQAACAQAbmFtZRUAbWluZWNyYWZ0OnNjYWZmb2xkaW5nBAkAbmFtZV9oYXNoYrkevrqcljwDCgBuZXR3b3JrX2lkD13mlAoGAHN0YXRlcwMJAHN0YWJpbGl0eQAAAAABDwBzdGFiaWxpdHlfY2hlY2sAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:smooth_stone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAAAACAQAbmFtZRsAbWluZWNyYWZ0OnNtb290aF9zdG9uZV9zbGFiBAkAbmFtZV9oYXNon5I1yVw74uMDCgBuZXR3b3JrX2lkqvjcBQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:normal_stone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCBAAACAQAbmFtZRsAbWluZWNyYWZ0Om5vcm1hbF9zdG9uZV9zbGFiBAkAbmFtZV9oYXNoIvsjJLQdolcDCgBuZXR3b3JrX2lkC1zqRQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:cobblestone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRoBAAACAQAbmFtZRoAbWluZWNyYWZ0OmNvYmJsZXN0b25lX3NsYWIECQBuYW1lX2hhc2h5CXtW7vlQVgMKAG5ldHdvcmtfaWRDGyj2CgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:mossy_cobblestone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR3BAAACAQAbmFtZSAAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lX3NsYWIECQBuYW1lX2hhc2ijm1BCwB82VgMKAG5ldHdvcmtfaWR7ByMGCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:oak_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAAAACAQAbmFtZRIAbWluZWNyYWZ0Om9ha19zbGFiBAkAbmFtZV9oYXNoJp1Cp1M4jlwDCgBuZXR3b3JrX2lkZH6+owoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:spruce_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQjBAAACAQAbmFtZRUAbWluZWNyYWZ0OnNwcnVjZV9zbGFiBAkAbmFtZV9oYXNodQi70jB238cDCgBuZXR3b3JrX2lkrriOYQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:birch_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQkBAAACAQAbmFtZRQAbWluZWNyYWZ0OmJpcmNoX3NsYWIECQBuYW1lX2hhc2gZPpfMxoOsTAMKAG5ldHdvcmtfaWThR9jyCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:jungle_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQlBAAACAQAbmFtZRUAbWluZWNyYWZ0Omp1bmdsZV9zbGFiBAkAbmFtZV9oYXNo6gLs79NXak4DCgBuZXR3b3JrX2lk5ZiKgwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:acacia_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmBAAACAQAbmFtZRUAbWluZWNyYWZ0OmFjYWNpYV9zbGFiBAkAbmFtZV9oYXNomSdFmDnv4OUDCgBuZXR3b3JrX2lkHttaXAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:dark_oak_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQnBAAACAQAbmFtZRcAbWluZWNyYWZ0OmRhcmtfb2FrX3NsYWIECQBuYW1lX2hhc2hJjTohRFyhIQMKAG5ldHdvcmtfaWRMzDTyCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:mangrove_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWToAgAACAQAbmFtZRcAbWluZWNyYWZ0Om1hbmdyb3ZlX3NsYWIECQBuYW1lX2hhc2jYCcmhJPeNMwMKAG5ldHdvcmtfaWQx6U1yCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:cherry_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQaAwAACAQAbmFtZRUAbWluZWNyYWZ0OmNoZXJyeV9zbGFiBAkAbmFtZV9oYXNoTt0MmVn/mqoDCgBuZXR3b3JrX2lk2VVsZQoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:bamboo_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQAAwAACAQAbmFtZRUAbWluZWNyYWZ0OmJhbWJvb19zbGFiBAkAbmFtZV9oYXNoo1xuFqINeLYDCgBuZXR3b3JrX2lkVC+0twoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:bamboo_mosaic_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQLAwAACAQAbmFtZRwAbWluZWNyYWZ0OmJhbWJvb19tb3NhaWNfc2xhYgQJAG5hbWVfaGFzaNbVRBZ/ChI3AwoAbmV0d29ya19pZOLZHFMKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:stone_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRqBAAACAQAbmFtZRoAbWluZWNyYWZ0OnN0b25lX2JyaWNrX3NsYWIECQBuYW1lX2hhc2js6EexuKuzrQMKAG5ldHdvcmtfaWRSsMxaCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:mossy_stone_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAQAACAQAbmFtZSAAbWluZWNyYWZ0Om1vc3N5X3N0b25lX2JyaWNrX3NsYWIECQBuYW1lX2hhc2hiA4kFUl4tHAMKAG5ldHdvcmtfaWS6joSOCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:sandstone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRnBAAACAQAbmFtZRgAbWluZWNyYWZ0OnNhbmRzdG9uZV9zbGFiBAkAbmFtZV9oYXNo/GMI0MZnrhsDCgBuZXR3b3JrX2lkFP8WmwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:cut_sandstone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDBAAACAQAbmFtZRwAbWluZWNyYWZ0OmN1dF9zYW5kc3RvbmVfc2xhYgQJAG5hbWVfaGFzaE+zxVQweViJAwoAbmV0d29ya19pZHsu74YKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:smooth_sandstone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR4BAAACAQAbmFtZR8AbWluZWNyYWZ0OnNtb290aF9zYW5kc3RvbmVfc2xhYgQJAG5hbWVfaGFzaIkmsO1gw3gnAwoAbmV0d29ya19pZFSiwP0KBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:red_sandstone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AAAACAQAbmFtZRwAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmVfc2xhYgQJAG5hbWVfaGFzaEyDjeWlUHItAwoAbmV0d29ya19pZIT4rmwKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:cut_red_sandstone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEBAAACAQAbmFtZSAAbWluZWNyYWZ0OmN1dF9yZWRfc2FuZHN0b25lX3NsYWIECQBuYW1lX2hhc2hTVRS++snU3wMKAG5ldHdvcmtfaWSvIAviCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:smooth_red_sandstone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR6BAAACAQAbmFtZSMAbWluZWNyYWZ0OnNtb290aF9yZWRfc2FuZHN0b25lX3NsYWIECQBuYW1lX2hhc2i9iN2UK272tgMKAG5ldHdvcmtfaWRUZrwJCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:granite_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR/BAAACAQAbmFtZRYAbWluZWNyYWZ0OmdyYW5pdGVfc2xhYgQJAG5hbWVfaGFzaL0HprlAhhZwAwoAbmV0d29ya19pZIcIdc8KBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:polished_granite_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSABAAACAQAbmFtZR8AbWluZWNyYWZ0OnBvbGlzaGVkX2dyYW5pdGVfc2xhYgQJAG5hbWVfaGFzaP6bXk5w2dGrAwoAbmV0d29ya19pZCsRy1cKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:diorite_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR9BAAACAQAbmFtZRYAbWluZWNyYWZ0OmRpb3JpdGVfc2xhYgQJAG5hbWVfaGFzaM3ppS8v55sNAwoAbmV0d29ya19pZB+Pv9oKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:polished_diorite_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR+BAAACAQAbmFtZR8AbWluZWNyYWZ0OnBvbGlzaGVkX2Rpb3JpdGVfc2xhYgQJAG5hbWVfaGFzaLZlyJLkMPhyAwoAbmV0d29ya19pZFM0HYwKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:andesite_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR8BAAACAQAbmFtZRcAbWluZWNyYWZ0OmFuZGVzaXRlX3NsYWIECQBuYW1lX2hhc2icIrtuy/aosAMKAG5ldHdvcmtfaWTtXTtYCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:polished_andesite_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR7BAAACAQAbmFtZSAAbWluZWNyYWZ0OnBvbGlzaGVkX2FuZGVzaXRlX3NsYWIECQBuYW1lX2hhc2j56zJOfCF+3wMKAG5ldHdvcmtfaWRBs69FCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRpBAAACAQAbmFtZRQAbWluZWNyYWZ0OmJyaWNrX3NsYWIECQBuYW1lX2hhc2hO/Da4jU2v4wMKAG5ldHdvcmtfaWRG/qphCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:nether_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRsBAAACAQAbmFtZRsAbWluZWNyYWZ0Om5ldGhlcl9icmlja19zbGFiBAkAbmFtZV9oYXNonymoa2zbbqMDCgBuZXR3b3JrX2lkquvR1QoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:red_nether_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR5BAAACAQAbmFtZR8AbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2tfc2xhYgQJAG5hbWVfaGFzaG89ujUk3Y64AwoAbmV0d29ya19pZEZIunAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:end_stone_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAQAACAQAbmFtZR4AbWluZWNyYWZ0OmVuZF9zdG9uZV9icmlja19zbGFiBAkAbmFtZV9oYXNo4tkxQtl+IyQDCgBuZXR3b3JrX2lkhByH/woGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:quartz_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRrBAAACAQAbmFtZRUAbWluZWNyYWZ0OnF1YXJ0el9zbGFiBAkAbmFtZV9oYXNo9JMj3upfsbwDCgBuZXR3b3JrX2lkn2g2VAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:smooth_quartz_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBBAAACAQAbmFtZRwAbWluZWNyYWZ0OnNtb290aF9xdWFydHpfc2xhYgQJAG5hbWVfaGFzaHOSJv8ve0nmAwoAbmV0d29ya19pZFMk/JsKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:purpur_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRzBAAACAQAbmFtZRUAbWluZWNyYWZ0OnB1cnB1cl9zbGFiBAkAbmFtZV9oYXNo4XeWbKpx2ScDCgBuZXR3b3JrX2lkRkga5goGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:prismarine_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR0BAAACAQAbmFtZRkAbWluZWNyYWZ0OnByaXNtYXJpbmVfc2xhYgQJAG5hbWVfaGFzaI9x+1fY8QRfAwoAbmV0d29ya19pZBTUZhwKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:dark_prismarine_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR1BAAACAQAbmFtZR4AbWluZWNyYWZ0OmRhcmtfcHJpc21hcmluZV9zbGFiBAkAbmFtZV9oYXNoSsZGDkEL5ZUDCgBuZXR3b3JrX2lkNLQ8VwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:prismarine_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR2BAAACAQAbmFtZR8AbWluZWNyYWZ0OnByaXNtYXJpbmVfYnJpY2tfc2xhYgQJAG5hbWVfaGFzaB1FSbVi97xJAwoAbmV0d29ya19pZEBwwFMKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:crimson_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAgAACAQAbmFtZRYAbWluZWNyYWZ0OmNyaW1zb25fc2xhYgQJAG5hbWVfaGFzaKZ+EfP0ZYOZAwoAbmV0d29ya19pZAxRUWAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:warped_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQIAgAACAQAbmFtZRUAbWluZWNyYWZ0OndhcnBlZF9zbGFiBAkAbmFtZV9oYXNo/AT0e/Z9W7UDCgBuZXR3b3JrX2lk1yq11AoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:blackstone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQZAgAACAQAbmFtZRkAbWluZWNyYWZ0OmJsYWNrc3RvbmVfc2xhYgQJAG5hbWVfaGFzaF/DD4ZUlNgtAwoAbmV0d29ya19pZGy1DjwKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:polished_blackstone_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQkAgAACAQAbmFtZSIAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfc2xhYgQJAG5hbWVfaGFzaDYnuUs86EWfAwoAbmV0d29ya19pZJj2bXIKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:polished_blackstone_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQbAgAACAQAbmFtZSgAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tfc2xhYgQJAG5hbWVfaGFzaKySLqvHc4xXAwoAbmV0d29ya19pZOyWX94KBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRoAgAACAQAbmFtZRkAbWluZWNyYWZ0OmN1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaDsNpb2qs4iBAwoAbmV0d29ya19pZOTm2nsKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:exposed_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRpAgAACAQAbmFtZSEAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcl9zbGFiBAkAbmFtZV9oYXNoahQ5OwIQb7kDCgBuZXR3b3JrX2lkrUlZLwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:weathered_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRqAgAACAQAbmFtZSMAbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyX3NsYWIECQBuYW1lX2hhc2hBIuGIOVVXogMKAG5ldHdvcmtfaWQgnaDiCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:oxidized_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRrAgAACAQAbmFtZSIAbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaOptj9ycfpaDAwoAbmV0d29ya19pZMzFSRgKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:waxed_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRsAgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaAlx6DZOCTHzAwoAbmV0d29ya19pZFRBvDAKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:waxed_exposed_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRtAgAACAQAbmFtZScAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcl9zbGFiBAkAbmFtZV9oYXNo3KqS5OnhtRIDCgBuZXR3b3JrX2lkHTGcTgoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:waxed_weathered_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRuAgAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyX3NsYWIECQBuYW1lX2hhc2gzZ1oX0HCFtwMKAG5ldHdvcmtfaWSgJR+XCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:waxed_oxidized_cut_copper_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTAAgAACAQAbmFtZSgAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXJfc2xhYgQJAG5hbWVfaGFzaMjjTnLu1KcqAwoAbmV0d29ya19pZIxsnFYKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:cobbled_deepslate_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR7AgAACAQAbmFtZSAAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlX3NsYWIECQBuYW1lX2hhc2gwJIVWK1TM2QMKAG5ldHdvcmtfaWTYAoX5CgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:polished_deepslate_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR/AgAACAQAbmFtZSEAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZV9zbGFiBAkAbmFtZV9oYXNoC/Adiz8k6RYDCgBuZXR3b3JrX2lkuFYMAAoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:deepslate_tile_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlX3NsYWIECQBuYW1lX2hhc2hPydV6emzIXAMKAG5ldHdvcmtfaWQwlbFCCgYAc3RhdGVzCBcAbWluZWNyYWZ0OnZlcnRpY2FsX2hhbGYGAGJvdHRvbQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:deepslate_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSHAgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja19zbGFiBAkAbmFtZV9oYXNoSv62V7iw10UDCgBuZXR3b3JrX2lkWMoragoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:mud_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAgAACAQAbmFtZRgAbWluZWNyYWZ0Om11ZF9icmlja19zbGFiBAkAbmFtZV9oYXNoq/tGBQWkv08DCgBuZXR3b3JrX2lkl4nnMwoGAHN0YXRlcwgXAG1pbmVjcmFmdDp2ZXJ0aWNhbF9oYWxmBgBib3R0b20AAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:brick_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQtAAAACAQAbmFtZRUAbWluZWNyYWZ0OmJyaWNrX2Jsb2NrBAkAbmFtZV9oYXNo5Qc2E005S3oDCgBuZXR3b3JrX2lkqeGWRgoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:chiseled_nether_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQtAgAACAQAbmFtZSAAbWluZWNyYWZ0OmNoaXNlbGVkX25ldGhlcl9icmlja3MECQBuYW1lX2hhc2g31SBPTcUK1QMKAG5ldHdvcmtfaWS8TJ+TCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:cracked_nether_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQuAgAACAQAbmFtZR8AbWluZWNyYWZ0OmNyYWNrZWRfbmV0aGVyX2JyaWNrcwQJAG5hbWVfaGFzaAdC6eKzXT5tAwoAbmV0d29ya19pZIUSejwKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:quartz_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQvAgAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9icmlja3MECQBuYW1lX2hhc2jSZO590dd8sAMKAG5ldHdvcmtfaWSc5xCLCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:stone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAAAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX2JyaWNrcwQJAG5hbWVfaGFzaGAiQu8VWVJRAwoAbmV0d29ya19pZH2DjXUKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:mossy_stone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjBAAACAQAbmFtZRwAbWluZWNyYWZ0Om1vc3N5X3N0b25lX2JyaWNrcwQJAG5hbWVfaGFzaIZBO00MONRIAwoAbmV0d29ya19pZL2WDrAKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:cracked_stone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRkBAAACAQAbmFtZR4AbWluZWNyYWZ0OmNyYWNrZWRfc3RvbmVfYnJpY2tzBAkAbmFtZV9oYXNocIkAp6riMz4DCgBuZXR3b3JrX2lkTWGeCwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:chiseled_stone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRlBAAACAQAbmFtZR8AbWluZWNyYWZ0OmNoaXNlbGVkX3N0b25lX2JyaWNrcwQJAG5hbWVfaGFzaMB2FPLLADkEAwoAbmV0d29ya19pZOIPn0IKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:end_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTOAAAACAQAbmFtZRQAbWluZWNyYWZ0OmVuZF9icmlja3MECQBuYW1lX2hhc2hIUFfxNLZaFgMKAG5ldHdvcmtfaWQ/vDihCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:prismarine_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzBAAACAQAbmFtZRsAbWluZWNyYWZ0OnByaXNtYXJpbmVfYnJpY2tzBAkAbmFtZV9oYXNozeGe3/7s5fcDCgBuZXR3b3JrX2lkj/iBnAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:polished_blackstone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQRAgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnJpY2tzBAkAbmFtZV9oYXNoIHgsgIdzKXcDCgBuZXR3b3JrX2lkUw9b3woGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:cracked_polished_blackstone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQXAgAACAQAbmFtZSwAbWluZWNyYWZ0OmNyYWNrZWRfcG9saXNoZWRfYmxhY2tzdG9uZV9icmlja3MECQBuYW1lX2hhc2jQIO1GQDk80AMKAG5ldHdvcmtfaWQ3UlRYCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:gilded_blackstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAgAACAQAbmFtZRsAbWluZWNyYWZ0OmdpbGRlZF9ibGFja3N0b25lBAkAbmFtZV9oYXNoNoWt1ocG0HEDCgBuZXR3b3JrX2lktL8gUwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:chiseled_polished_blackstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQWAgAACAQAbmFtZSYAbWluZWNyYWZ0OmNoaXNlbGVkX3BvbGlzaGVkX2JsYWNrc3RvbmUECQBuYW1lX2hhc2gzFa+kEjCJgAMKAG5ldHdvcmtfaWR2NJX2CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:deepslate_tiles", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAgAACAQAbmFtZRkAbWluZWNyYWZ0OmRlZXBzbGF0ZV90aWxlcwQJAG5hbWVfaGFzaGcLLx3NXAFvAwoAbmV0d29ya19pZI/G/xYKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:cracked_deepslate_tiles", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSYAgAACAQAbmFtZSEAbWluZWNyYWZ0OmNyYWNrZWRfZGVlcHNsYXRlX3RpbGVzBAkAbmFtZV9oYXNo9zWgkFuMM1QDCgBuZXR3b3JrX2lkGwY6OgoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:deepslate_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSGAgAACAQAbmFtZRoAbWluZWNyYWZ0OmRlZXBzbGF0ZV9icmlja3MECQBuYW1lX2hhc2gucvFmPdZxigMKAG5ldHdvcmtfaWSH4HDPCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:cracked_deepslate_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSZAgAACAQAbmFtZSIAbWluZWNyYWZ0OmNyYWNrZWRfZGVlcHNsYXRlX2JyaWNrcwQJAG5hbWVfaGFzaN40aqhh9WqHAwoAbmV0d29ya19pZO9GPBQKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:chiseled_deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAgAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaEU7/uRG8HSBAwoAbmV0d29ya19pZEqmI0EKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:cobblestone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQEAAAACAQAbmFtZRUAbWluZWNyYWZ0OmNvYmJsZXN0b25lBAkAbmFtZV9oYXNoPoK7mGlSUz4DCgBuZXR3b3JrX2lkLm7RZwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:mossy_cobblestone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQwAAAACAQAbmFtZRsAbWluZWNyYWZ0Om1vc3N5X2NvYmJsZXN0b25lBAkAbmFtZV9oYXNoGJ67FCbkChMDCgBuZXR3b3JrX2lk/pYs1AoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:cobbled_deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR6AgAACAQAbmFtZRsAbWluZWNyYWZ0OmNvYmJsZWRfZGVlcHNsYXRlBAkAbmFtZV9oYXNoLUz9Y/ywmLwDCgBuZXR3b3JrX2lkNwzZ+AoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:smooth_stone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2AQAACAQAbmFtZRYAbWluZWNyYWZ0OnNtb290aF9zdG9uZQQJAG5hbWVfaGFzaMwf87/JaTNvAwoAbmV0d29ya19pZLkZICEKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNhbmRzdG9uZQQJAG5hbWVfaGFzaFEmWsEHFI1AAwoAbmV0d29ya19pZPsXMaQKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:chiseled_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvBAAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX3NhbmRzdG9uZQQJAG5hbWVfaGFzaPEkxMvZmemgAwoAbmV0d29ya19pZGI5NB4KBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:cut_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSwBAAACAQAbmFtZRcAbWluZWNyYWZ0OmN1dF9zYW5kc3RvbmUECQBuYW1lX2hhc2ichLQc71njnQMKAG5ldHdvcmtfaWSmBLkRCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:smooth_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSxBAAACAQAbmFtZRoAbWluZWNyYWZ0OnNtb290aF9zYW5kc3RvbmUECQBuYW1lX2hhc2huR7XTwISyCAMKAG5ldHdvcmtfaWSzWj3UCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:red_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSzAAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2jBO4Gv2v59uAMKAG5ldHdvcmtfaWRXRYxZCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:chiseled_red_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS7BAAACAQAbmFtZSAAbWluZWNyYWZ0OmNoaXNlbGVkX3JlZF9zYW5kc3RvbmUECQBuYW1lX2hhc2gh5sX+ON054wMKAG5ldHdvcmtfaWT6Pw1PCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:cut_red_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS8BAAACAQAbmFtZRsAbWluZWNyYWZ0OmN1dF9yZWRfc2FuZHN0b25lBAkAbmFtZV9oYXNoaOtka4NrQ1EDCgBuZXR3b3JrX2lk3r/JPAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:smooth_red_sandstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS9BAAACAQAbmFtZR4AbWluZWNyYWZ0OnNtb290aF9yZWRfc2FuZHN0b25lBAkAbmFtZV9oYXNoqsNl8x36ju4DCgBuZXR3b3JrX2lk7x5DTwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:coal_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWStAAAACAQAbmFtZRQAbWluZWNyYWZ0OmNvYWxfYmxvY2sECQBuYW1lX2hhc2jH8QQP3t5PiAMKAG5ldHdvcmtfaWRo+sR+CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:dried_kelp_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSKAQAACAQAbmFtZRoAbWluZWNyYWZ0OmRyaWVkX2tlbHBfYmxvY2sECQBuYW1lX2hhc2iRoucexkrl8wMKAG5ldHdvcmtfaWQQCCrvCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:gold_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQpAAAACAQAbmFtZRQAbWluZWNyYWZ0OmdvbGRfYmxvY2sECQBuYW1lX2hhc2iYLshvjtXzFwMKAG5ldHdvcmtfaWTDJGBcCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:iron_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQqAAAACAQAbmFtZRQAbWluZWNyYWZ0Omlyb25fYmxvY2sECQBuYW1lX2hhc2jYINmJQbvV/gMKAG5ldHdvcmtfaWRf7AbICgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:copper_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRTAgAACAQAbmFtZRYAbWluZWNyYWZ0OmNvcHBlcl9ibG9jawQJAG5hbWVfaGFzaDVxnehsGaZ1AwoAbmV0d29ya19pZIiUodwKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:copper_door" + }, + { + "id": "minecraft:copper_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQXBAAACAQAbmFtZRkAbWluZWNyYWZ0OmNvcHBlcl90cmFwZG9vcgQJAG5hbWVfaGFzaO9fXio+svKVAwoAbmV0d29ya19pZMCoRjEKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:copper_grate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT/AwAACAQAbmFtZRYAbWluZWNyYWZ0OmNvcHBlcl9ncmF0ZQQJAG5hbWVfaGFzaC/JEFOWnmEcAwoAbmV0d29ya19pZC6YiiMKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:exposed_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRUAgAACAQAbmFtZRgAbWluZWNyYWZ0OmV4cG9zZWRfY29wcGVyBAkAbmFtZV9oYXNoQH3Fukmu3CEDCgBuZXR3b3JrX2lk72jFIwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:exposed_copper_door" + }, + { + "id": "minecraft:exposed_copper_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQYBAAACAQAbmFtZSEAbWluZWNyYWZ0OmV4cG9zZWRfY29wcGVyX3RyYXBkb29yBAkAbmFtZV9oYXNoYhDFUysN7qUDCgBuZXR3b3JrX2lkMzwGJgoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:exposed_copper_grate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQABAAACAQAbmFtZR4AbWluZWNyYWZ0OmV4cG9zZWRfY29wcGVyX2dyYXRlBAkAbmFtZV9oYXNolFIBYLYU0IcDCgBuZXR3b3JrX2lk4UqptAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:weathered_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRVAgAACAQAbmFtZRoAbWluZWNyYWZ0OndlYXRoZXJlZF9jb3BwZXIECQBuYW1lX2hhc2hJCQXbvobv+gMKAG5ldHdvcmtfaWQwM0lJCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:weathered_copper_door" + }, + { + "id": "minecraft:weathered_copper_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQZBAAACAQAbmFtZSMAbWluZWNyYWZ0OndlYXRoZXJlZF9jb3BwZXJfdHJhcGRvb3IECQBuYW1lX2hhc2hFnEC282a1tgMKAG5ldHdvcmtfaWTk70oiCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:weathered_copper_grate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBBAAACAQAbmFtZSAAbWluZWNyYWZ0OndlYXRoZXJlZF9jb3BwZXJfZ3JhdGUECQBuYW1lX2hhc2jB3o8enlv1RgMKAG5ldHdvcmtfaWRih2pOCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:oxidized_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRWAgAACAQAbmFtZRkAbWluZWNyYWZ0Om94aWRpemVkX2NvcHBlcgQJAG5hbWVfaGFzaMDtJqR0G5Y7AwoAbmV0d29ya19pZGjN8bUKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:oxidized_copper_door" + }, + { + "id": "minecraft:oxidized_copper_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQaBAAACAQAbmFtZSIAbWluZWNyYWZ0Om94aWRpemVkX2NvcHBlcl90cmFwZG9vcgQJAG5hbWVfaGFzaOJpG/XFexVwAwoAbmV0d29ya19pZPhi0J4KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:oxidized_copper_grate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCBAAACAQAbmFtZR8AbWluZWNyYWZ0Om94aWRpemVkX2NvcHBlcl9ncmF0ZQQJAG5hbWVfaGFzaBRfNhyndve7AwoAbmV0d29ya19pZKY2cnEKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:waxed_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRXAgAACAQAbmFtZRYAbWluZWNyYWZ0OndheGVkX2NvcHBlcgQJAG5hbWVfaGFzaPF+FG6Eh5fsAwoAbmV0d29ya19pZIjtz/0KBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:waxed_copper_door" + }, + { + "id": "minecraft:waxed_copper_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQbBAAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX2NvcHBlcl90cmFwZG9vcgQJAG5hbWVfaGFzaO0JUKUHqNU6AwoAbmV0d29ya19pZJC3ZuMKBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:waxed_copper_grate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDBAAACAQAbmFtZRwAbWluZWNyYWZ0OndheGVkX2NvcHBlcl9ncmF0ZQQJAG5hbWVfaGFzaDmC92M2RO+HAwoAbmV0d29ya19pZH4og2AKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:waxed_exposed_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRYAgAACAQAbmFtZR4AbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY29wcGVyBAkAbmFtZV9oYXNoig8IOc+SCikDCgBuZXR3b3JrX2lklz8yWQoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:waxed_exposed_copper_door" + }, + { + "id": "minecraft:waxed_exposed_copper_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQcBAAACAQAbmFtZScAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY29wcGVyX3RyYXBkb29yBAkAbmFtZV9oYXNoBHHxCpkUzpgDCgBuZXR3b3JrX2lkw2XBGQoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAABCABvcGVuX2JpdAABDwB1cHNpZGVfZG93bl9iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:waxed_exposed_copper_grate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQEBAAACAQAbmFtZSQAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY29wcGVyX2dyYXRlBAkAbmFtZV9oYXNoWmd6B+hWwiEDCgBuZXR3b3JrX2lk8d4ZQwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:waxed_weathered_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRZAgAACAQAbmFtZSAAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jb3BwZXIECQBuYW1lX2hhc2gjtPq8MOdvKgMKAG5ldHdvcmtfaWSQ9Ln9CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:waxed_weathered_copper_door" + }, + { + "id": "minecraft:waxed_weathered_copper_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQdBAAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jb3BwZXJfdHJhcGRvb3IECQBuYW1lX2hhc2gH9Fi3JCF4egMKAG5ldHdvcmtfaWRkGU6TCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAEPAHVwc2lkZV9kb3duX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:waxed_weathered_copper_grate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQFBAAACAQAbmFtZSYAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jb3BwZXJfZ3JhdGUECQBuYW1lX2hhc2hXfilVFDAiYQMKAG5ldHdvcmtfaWQqTGC1CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:waxed_oxidized_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS9AgAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NvcHBlcgQJAG5hbWVfaGFzaMaORhsO+LzjAwoAbmV0d29ya19pZJhGfLEKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:waxed_oxidized_copper_door" + }, + { + "id": "minecraft:waxed_oxidized_copper_trapdoor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQeBAAACAQAbmFtZSgAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NvcHBlcl90cmFwZG9vcgQJAG5hbWVfaGFzaNA/q9qAy6Z9AwoAbmV0d29ya19pZDgExS8KBgBzdGF0ZXMDCQBkaXJlY3Rpb24AAAAAAQgAb3Blbl9iaXQAAQ8AdXBzaWRlX2Rvd25fYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:waxed_oxidized_copper_grate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGBAAACAQAbmFtZSUAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NvcHBlcl9ncmF0ZQQJAG5hbWVfaGFzaEbeMT605GP4AwoAbmV0d29ya19pZOZjpkkKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRaAgAACAQAbmFtZRQAbWluZWNyYWZ0OmN1dF9jb3BwZXIECQBuYW1lX2hhc2hAfN3NGax3eAMKAG5ldHdvcmtfaWTnFBtYCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:exposed_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRbAgAACAQAbmFtZRwAbWluZWNyYWZ0OmV4cG9zZWRfY3V0X2NvcHBlcgQJAG5hbWVfaGFzaA85G3yv/w6pAwoAbmV0d29ya19pZMQhr0QKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:weathered_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRcAgAACAQAbmFtZR4AbWluZWNyYWZ0OndlYXRoZXJlZF9jdXRfY29wcGVyBAkAbmFtZV9oYXNoVgRV0fBaz88DCgBuZXR3b3JrX2lk/0cYugoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:oxidized_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRdAgAACAQAbmFtZR0AbWluZWNyYWZ0Om94aWRpemVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2iP8WmFWOkriwMKAG5ldHdvcmtfaWQPdce7CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:waxed_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWReAgAACAQAbmFtZRoAbWluZWNyYWZ0OndheGVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2jumiwOZIqv2AMKAG5ldHdvcmtfaWQvuxx9CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:waxed_exposed_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRfAgAACAQAbmFtZSIAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY3V0X2NvcHBlcgQJAG5hbWVfaGFzaPE/OfK6IoVMAwoAbmV0d29ya19pZHy5HkcKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:waxed_weathered_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRgAgAACAQAbmFtZSQAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jdXRfY29wcGVyBAkAbmFtZV9oYXNoCA1xDp11bnwDCgBuZXR3b3JrX2lkDyEDVQoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:waxed_oxidized_cut_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS+AgAACAQAbmFtZSMAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2N1dF9jb3BwZXIECQBuYW1lX2hhc2i1pZAsZYHLDAMKAG5ldHdvcmtfaWQ/wSkCCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:chiseled_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT3AwAACAQAbmFtZRkAbWluZWNyYWZ0OmNoaXNlbGVkX2NvcHBlcgQJAG5hbWVfaGFzaIsW5pmpJEuQAwoAbmV0d29ya19pZHetwrkKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:exposed_chiseled_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT4AwAACAQAbmFtZSEAbWluZWNyYWZ0OmV4cG9zZWRfY2hpc2VsZWRfY29wcGVyBAkAbmFtZV9oYXNoOvrLJ0UowbgDCgBuZXR3b3JrX2lkZj7cPwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:weathered_chiseled_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT5AwAACAQAbmFtZSMAbWluZWNyYWZ0OndlYXRoZXJlZF9jaGlzZWxlZF9jb3BwZXIECQBuYW1lX2hhc2hh+42XlsWvGAMKAG5ldHdvcmtfaWS7Cy59CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:oxidized_chiseled_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT6AwAACAQAbmFtZSIAbWluZWNyYWZ0Om94aWRpemVkX2NoaXNlbGVkX2NvcHBlcgQJAG5hbWVfaGFzaLpTIsnfluiCAwoAbmV0d29ya19pZB9/jS8KBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:waxed_chiseled_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT7AwAACAQAbmFtZR8AbWluZWNyYWZ0OndheGVkX2NoaXNlbGVkX2NvcHBlcgQJAG5hbWVfaGFzaFnXvXY5OinzAwoAbmV0d29ya19pZAcKtHsKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:waxed_exposed_chiseled_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT8AwAACAQAbmFtZScAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY2hpc2VsZWRfY29wcGVyBAkAbmFtZV9oYXNoHJdq+Pph6hMDCgBuZXR3b3JrX2lkdge7IAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:waxed_oxidized_chiseled_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT9AwAACAQAbmFtZSgAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NoaXNlbGVkX2NvcHBlcgQJAG5hbWVfaGFzaMj49OvlTpgCAwoAbmV0d29ya19pZN/r+roKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:waxed_weathered_chiseled_copper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT+AwAACAQAbmFtZSkAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jaGlzZWxlZF9jb3BwZXIECQBuYW1lX2hhc2hzuO+Sg9LYQwMKAG5ldHdvcmtfaWQ7AN7iCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:copper_bulb", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHBAAACAQAbmFtZRUAbWluZWNyYWZ0OmNvcHBlcl9idWxiBAkAbmFtZV9oYXNo41TimHOsMWcDCgBuZXR3b3JrX2lkJnZvAgoGAHN0YXRlcwEDAGxpdAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:exposed_copper_bulb", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQIBAAACAQAbmFtZR0AbWluZWNyYWZ0OmV4cG9zZWRfY29wcGVyX2J1bGIECQBuYW1lX2hhc2g++f1wYLLCrAMKAG5ldHdvcmtfaWRLdMmGCgYAc3RhdGVzAQMAbGl0AAELAHBvd2VyZWRfYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:weathered_copper_bulb", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQJBAAACAQAbmFtZR8AbWluZWNyYWZ0OndlYXRoZXJlZF9jb3BwZXJfYnVsYgQJAG5hbWVfaGFzaMEtsYfwRTXlAwoAbmV0d29ya19pZAp51LQKBgBzdGF0ZXMBAwBsaXQAAQsAcG93ZXJlZF9iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:oxidized_copper_bulb", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQKBAAACAQAbmFtZR4AbWluZWNyYWZ0Om94aWRpemVkX2NvcHBlcl9idWxiBAkAbmFtZV9oYXNovnrBQZs8nDIDCgBuZXR3b3JrX2lkPsj0AAoGAHN0YXRlcwEDAGxpdAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:waxed_copper_bulb", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQLBAAACAQAbmFtZRsAbWluZWNyYWZ0OndheGVkX2NvcHBlcl9idWxiBAkAbmFtZV9oYXNoGTg6TYllMiIDCgBuZXR3b3JrX2lk9m0WhgoGAHN0YXRlcwEDAGxpdAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:waxed_exposed_copper_bulb", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQMBAAACAQAbmFtZSMAbWluZWNyYWZ0OndheGVkX2V4cG9zZWRfY29wcGVyX2J1bGIECQBuYW1lX2hhc2gI6xkPcvBDVwMKAG5ldHdvcmtfaWR7BRcACgYAc3RhdGVzAQMAbGl0AAELAHBvd2VyZWRfYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:waxed_weathered_copper_bulb", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQNBAAACAQAbmFtZSUAbWluZWNyYWZ0OndheGVkX3dlYXRoZXJlZF9jb3BwZXJfYnVsYgQJAG5hbWVfaGFzaMsUnmp3/VqVAwoAbmV0d29ya19pZEoworoKBgBzdGF0ZXMBAwBsaXQAAQsAcG93ZXJlZF9iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:waxed_oxidized_copper_bulb", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQOBAAACAQAbmFtZSQAbWluZWNyYWZ0OndheGVkX294aWRpemVkX2NvcHBlcl9idWxiBAkAbmFtZV9oYXNoBFKxY3fjVq4DCgBuZXR3b3JrX2lkzrJ6aAoGAHN0YXRlcwEDAGxpdAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:emerald_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAAAACAQAbmFtZRcAbWluZWNyYWZ0OmVtZXJhbGRfYmxvY2sECQBuYW1lX2hhc2hK6QunqJznNAMKAG5ldHdvcmtfaWRk5+otCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:diamond_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ5AAAACAQAbmFtZRcAbWluZWNyYWZ0OmRpYW1vbmRfYmxvY2sECQBuYW1lX2hhc2iGKrxuvkytFQMKAG5ldHdvcmtfaWQQeQZXCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:lapis_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQWAAAACAQAbmFtZRUAbWluZWNyYWZ0OmxhcGlzX2Jsb2NrBAkAbmFtZV9oYXNoDZ44xdb2zVoDCgBuZXR3b3JrX2lktVy0BAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:raw_iron_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTCAgAACAQAbmFtZRgAbWluZWNyYWZ0OnJhd19pcm9uX2Jsb2NrBAkAbmFtZV9oYXNo9XyzNIQXxvwDCgBuZXR3b3JrX2lknms1QAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:raw_copper_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTDAgAACAQAbmFtZRoAbWluZWNyYWZ0OnJhd19jb3BwZXJfYmxvY2sECQBuYW1lX2hhc2hw1KG0TNUGgwMKAG5ldHdvcmtfaWS1vGo/CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:raw_gold_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTEAgAACAQAbmFtZRgAbWluZWNyYWZ0OnJhd19nb2xkX2Jsb2NrBAkAbmFtZV9oYXNo6YuwuLwfOBwDCgBuZXR3b3JrX2lkLiQ5gQoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:quartz_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAAAACAQAbmFtZRYAbWluZWNyYWZ0OnF1YXJ0el9ibG9jawQJAG5hbWVfaGFzaCfpbqyIIvZCAwoAbmV0d29ya19pZE2axGsKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:quartz_pillar", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS5BAAACAQAbmFtZRcAbWluZWNyYWZ0OnF1YXJ0el9waWxsYXIECQBuYW1lX2hhc2igp62HI+PuSwMKAG5ldHdvcmtfaWS9SGXLCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:chiseled_quartz_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS4BAAACAQAbmFtZR8AbWluZWNyYWZ0OmNoaXNlbGVkX3F1YXJ0el9ibG9jawQJAG5hbWVfaGFzaAftJM9mCAvaAwoAbmV0d29ya19pZFwy0s0KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:smooth_quartz", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS6BAAACAQAbmFtZRcAbWluZWNyYWZ0OnNtb290aF9xdWFydHoECQBuYW1lX2hhc2hIVzzgiItGagMKAG5ldHdvcmtfaWTVWgU2CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:prismarine", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAAAACAQAbmFtZRQAbWluZWNyYWZ0OnByaXNtYXJpbmUECQBuYW1lX2hhc2jcnQCHi9CspQMKAG5ldHdvcmtfaWQnuuW1CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:dark_prismarine", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSyBAAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfcHJpc21hcmluZQQJAG5hbWVfaGFzaK+rhxsgkzplAwoAbmV0d29ya19pZIdA0I0KBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:slime", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAAAACAQAbmFtZQ8AbWluZWNyYWZ0OnNsaW1lBAkAbmFtZV9oYXNoHJiEEJx+JlkDCgBuZXR3b3JrX2lkfgfVzAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:honey_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTbAQAACAQAbmFtZRUAbWluZWNyYWZ0OmhvbmV5X2Jsb2NrBAkAbmFtZV9oYXNo9zLYSUlelywDCgBuZXR3b3JrX2lko+dyWgoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:honeycomb_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAQAACAQAbmFtZRkAbWluZWNyYWZ0OmhvbmV5Y29tYl9ibG9jawQJAG5hbWVfaGFzaASIPuOCYd1oAwoAbmV0d29ya19pZKys4n4KBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:hay_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAAAACAQAbmFtZRMAbWluZWNyYWZ0OmhheV9ibG9jawQJAG5hbWVfaGFzaIB2VxKxX8EpAwoAbmV0d29ya19pZKuQSloKBgBzdGF0ZXMDCgBkZXByZWNhdGVkAAAAAAgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:bone_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTYAAAACAQAbmFtZRQAbWluZWNyYWZ0OmJvbmVfYmxvY2sECQBuYW1lX2hhc2i4ZX576W9AWgMKAG5ldHdvcmtfaWTWGacQCgYAc3RhdGVzAwoAZGVwcmVjYXRlZAAAAAAICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:nether_brick", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRwAAAACAQAbmFtZRYAbWluZWNyYWZ0Om5ldGhlcl9icmljawQJAG5hbWVfaGFzaMxcRiheU+nXAwoAbmV0d29ya19pZMkmzloKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:red_nether_brick", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAAAACAQAbmFtZRoAbWluZWNyYWZ0OnJlZF9uZXRoZXJfYnJpY2sECQBuYW1lX2hhc2j8pRO4LfoECAMKAG5ldHdvcmtfaWRpdF0YCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:netherite_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQNAgAACAQAbmFtZRkAbWluZWNyYWZ0Om5ldGhlcml0ZV9ibG9jawQJAG5hbWVfaGFzaMghh6Zib/ZKAwoAbmV0d29ya19pZIz0mq0KBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:lodestone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAQAACAQAbmFtZRMAbWluZWNyYWZ0OmxvZGVzdG9uZQQJAG5hbWVfaGFzaJ2gmHOTlXv8AwoAbmV0d29ya19pZEfgB4wKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:white_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQjAAAACAQAbmFtZRQAbWluZWNyYWZ0OndoaXRlX3dvb2wECQBuYW1lX2hhc2jRWB7vaIEDiQMKAG5ldHdvcmtfaWSO8paQCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:light_gray_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQnAwAACAQAbmFtZRkAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfd29vbAQJAG5hbWVfaGFzaOpdQ1a2v4b3AwoAbmV0d29ya19pZIqZCYEKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:gray_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQoAwAACAQAbmFtZRMAbWluZWNyYWZ0OmdyYXlfd29vbAQJAG5hbWVfaGFzaLsc1Lp1xdIOAwoAbmV0d29ya19pZFUs+HgKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:black_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQpAwAACAQAbmFtZRQAbWluZWNyYWZ0OmJsYWNrX3dvb2wECQBuYW1lX2hhc2hP2HC6o0X4HAMKAG5ldHdvcmtfaWRUbORcCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:brown_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQqAwAACAQAbmFtZRQAbWluZWNyYWZ0OmJyb3duX3dvb2wECQBuYW1lX2hhc2ig5IW89PrREwMKAG5ldHdvcmtfaWRjT9j8CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:red_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQrAwAACAQAbmFtZRIAbWluZWNyYWZ0OnJlZF93b29sBAkAbmFtZV9oYXNoY4TBDq+mFgUDCgBuZXR3b3JrX2lktn9lcAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:orange_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAwAACAQAbmFtZRUAbWluZWNyYWZ0Om9yYW5nZV93b29sBAkAbmFtZV9oYXNoFstfrTZfSCgDCgBuZXR3b3JrX2lk+rqywwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:yellow_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQtAwAACAQAbmFtZRUAbWluZWNyYWZ0OnllbGxvd193b29sBAkAbmFtZV9oYXNoTFyus2RHegcDCgBuZXR3b3JrX2lkkKBhXAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:lime_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQuAwAACAQAbmFtZRMAbWluZWNyYWZ0OmxpbWVfd29vbAQJAG5hbWVfaGFzaNVnnzKiMxmeAwoAbmV0d29ya19pZG9b32kKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:green_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQvAwAACAQAbmFtZRQAbWluZWNyYWZ0OmdyZWVuX3dvb2wECQBuYW1lX2hhc2i3mElRYHIcSQMKAG5ldHdvcmtfaWSssprwCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:cyan_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQwAwAACAQAbmFtZRMAbWluZWNyYWZ0OmN5YW5fd29vbAQJAG5hbWVfaGFzaBNDfvHn8dqFAwoAbmV0d29ya19pZK0hAbgKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:light_blue_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQxAwAACAQAbmFtZRkAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfd29vbAQJAG5hbWVfaGFzaLWFAUfyxFPNAwoAbmV0d29ya19pZL2oEugKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:blue_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQyAwAACAQAbmFtZRMAbWluZWNyYWZ0OmJsdWVfd29vbAQJAG5hbWVfaGFzaLjHyxxbTWCLAwoAbmV0d29ya19pZPaLdFQKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:purple_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQzAwAACAQAbmFtZRUAbWluZWNyYWZ0OnB1cnBsZV93b29sBAkAbmFtZV9oYXNojvFtqzjAf/4DCgBuZXR3b3JrX2lklqASNQoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:magenta_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ0AwAACAQAbmFtZRYAbWluZWNyYWZ0Om1hZ2VudGFfd29vbAQJAG5hbWVfaGFzaGuOHvf+Pd4yAwoAbmV0d29ya19pZI4UoDQKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:pink_wool", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ1AwAACAQAbmFtZRMAbWluZWNyYWZ0OnBpbmtfd29vbAQJAG5hbWVfaGFzaPiVA2pFeoFLAwoAbmV0d29ya19pZOZRO6oKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:white_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAAAACAQAbmFtZRYAbWluZWNyYWZ0OndoaXRlX2NhcnBldAQJAG5hbWVfaGFzaNeMHTI1fWPXAwoAbmV0d29ya19pZEahDFcKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:light_gray_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRbAwAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY2FycGV0BAkAbmFtZV9oYXNoHPw6ArBAsP0DCgBuZXR3b3JrX2lkQoAeUAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:gray_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRaAwAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXlfY2FycGV0BAkAbmFtZV9oYXNoZVR0OI+1VRADCgBuZXR3b3JrX2lkETF4WwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:black_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJsYWNrX2NhcnBldAQJAG5hbWVfaGFzaOk7LP9NptyhAwoAbmV0d29ya19pZFjmXtIKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:brown_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRfAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJyb3duX2NhcnBldAQJAG5hbWVfaGFzaNaXFyOsAvIvAwoAbmV0d29ya19pZHPjFuoKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:red_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAwAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9jYXJwZXQECQBuYW1lX2hhc2i9eSKBf6SO3wMKAG5ldHdvcmtfaWQuhI/KCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:orange_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRUAwAACAQAbmFtZRcAbWluZWNyYWZ0Om9yYW5nZV9jYXJwZXQECQBuYW1lX2hhc2hIUkO4HlAdygMKAG5ldHdvcmtfaWSyKV9OCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:yellow_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRXAwAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19jYXJwZXQECQBuYW1lX2hhc2hSDKX3scCamwMKAG5ldHdvcmtfaWT8nq+ECgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:lime_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRYAwAACAQAbmFtZRUAbWluZWNyYWZ0OmxpbWVfY2FycGV0BAkAbmFtZV9oYXNo+6KFOpzsib4DCgBuZXR3b3JrX2lkT+DS4woGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:green_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRgAwAACAQAbmFtZRYAbWluZWNyYWZ0OmdyZWVuX2NhcnBldAQJAG5hbWVfaGFzaCHPMP9ltqFJAwoAbmV0d29ya19pZBgwAvAKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:cyan_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRcAwAACAQAbmFtZRUAbWluZWNyYWZ0OmN5YW5fY2FycGV0BAkAbmFtZV9oYXNobXf62dQBJj8DCgBuZXR3b3JrX2lkKVppLgoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:light_blue_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRWAwAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY2FycGV0BAkAbmFtZV9oYXNo20l4oktdZ3sDCgBuZXR3b3JrX2lkjdeMiwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:blue_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWReAwAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfY2FycGV0BAkAbmFtZV9oYXNo3p3lsW0eQwsDCgBuZXR3b3JrX2lkAovdPQoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:purple_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRdAwAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnBsZV9jYXJwZXQECQBuYW1lX2hhc2jwIA9pW/qp7QMKAG5ldHdvcmtfaWTqJqhjCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:magenta_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRVAwAACAQAbmFtZRgAbWluZWNyYWZ0Om1hZ2VudGFfY2FycGV0BAkAbmFtZV9oYXNoFXT36YNNZhMDCgBuZXR3b3JrX2lk+tqsGAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:pink_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRZAwAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfY2FycGV0BAkAbmFtZV9oYXNoHll72oqk+OoDCgBuZXR3b3JrX2lkrnBYDwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:white_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTtAAAACAQAbmFtZR8AbWluZWNyYWZ0OndoaXRlX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaFUk9iXVjwV8AwoAbmV0d29ya19pZJPZY8AKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:light_gray_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAwAACAQAbmFtZSQAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNo7EUk30hmUtYDCgBuZXR3b3JrX2lkh8jVIwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:gray_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTKAwAACAQAbmFtZR4AbWluZWNyYWZ0OmdyYXlfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoW77af6WihdwDCgBuZXR3b3JrX2lkSsqC1woGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:black_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTSAwAACAQAbmFtZR8AbWluZWNyYWZ0OmJsYWNrX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaAfWYp0xtgcfAwoAbmV0d29ya19pZMWTC8EKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:brown_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTPAwAACAQAbmFtZR8AbWluZWNyYWZ0OmJyb3duX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaB74EeiLO46XAwoAbmV0d29ya19pZEDHKqwKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:red_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTRAwAACAQAbmFtZR0AbWluZWNyYWZ0OnJlZF9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2gjFut6Z/VH1gMKAG5ldHdvcmtfaWSvcmwYCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:orange_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTEAwAACAQAbmFtZSAAbWluZWNyYWZ0Om9yYW5nZV9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2gADDj2IJiw+gMKAG5ldHdvcmtfaWTHph0FCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:yellow_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTHAwAACAQAbmFtZSAAbWluZWNyYWZ0OnllbGxvd19jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2iy6qKNn3ob5wMKAG5ldHdvcmtfaWQZAI39CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:lime_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTIAwAACAQAbmFtZR4AbWluZWNyYWZ0OmxpbWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNo4dYIPslbXPUDCgBuZXR3b3JrX2lk2O8X0AoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:green_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTQAwAACAQAbmFtZR8AbWluZWNyYWZ0OmdyZWVuX2NvbmNyZXRlX3Bvd2RlcgQJAG5hbWVfaGFzaM/c9x2aJh3HAwoAbmV0d29ya19pZA0VfBMKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:cyan_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTMAwAACAQAbmFtZR4AbWluZWNyYWZ0OmN5YW5fY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNok+xKAe7XXjoDCgBuZXR3b3JrX2lkmkn6uwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:light_blue_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTGAwAACAQAbmFtZSQAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNogScpIQceyAEDCgBuZXR3b3JrX2lkOmVSbgoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:blue_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTOAwAACAQAbmFtZR4AbWluZWNyYWZ0OmJsdWVfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoFp7mmeL86r0DCgBuZXR3b3JrX2lkS3b3RQoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:purple_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTNAwAACAQAbmFtZSAAbWluZWNyYWZ0OnB1cnBsZV9jb25jcmV0ZV9wb3dkZXIECQBuYW1lX2hhc2iYcVU04hoStwMKAG5ldHdvcmtfaWQXimEjCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:magenta_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTFAwAACAQAbmFtZSEAbWluZWNyYWZ0Om1hZ2VudGFfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoy/70q6VPsWgDCgBuZXR3b3JrX2lkf9mxQwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:pink_concrete_powder", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAwAACAQAbmFtZR4AbWluZWNyYWZ0OnBpbmtfY29uY3JldGVfcG93ZGVyBAkAbmFtZV9oYXNoVikSAf8DwV0DCgBuZXR3b3JrX2lku2MivwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:white_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTsAAAACAQAbmFtZRgAbWluZWNyYWZ0OndoaXRlX2NvbmNyZXRlBAkAbmFtZV9oYXNo6zAp7lsLlvkDCgBuZXR3b3JrX2lk3MAYQAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:light_gray_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR6AwAACAQAbmFtZR0AbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY29uY3JldGUECQBuYW1lX2hhc2hEtet5wuDIKAMKAG5ldHdvcmtfaWQISs02CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:gray_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR5AwAACAQAbmFtZRcAbWluZWNyYWZ0OmdyYXlfY29uY3JldGUECQBuYW1lX2hhc2j92INnb0a83AMKAG5ldHdvcmtfaWQj8RHwCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:black_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAwAACAQAbmFtZRgAbWluZWNyYWZ0OmJsYWNrX2NvbmNyZXRlBAkAbmFtZV9oYXNo2X7NDIQmZ70DCgBuZXR3b3JrX2lk2uiVDQoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:brown_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR+AwAACAQAbmFtZRgAbWluZWNyYWZ0OmJyb3duX2NvbmNyZXRlBAkAbmFtZV9oYXNoeka02BwXf6oDCgBuZXR3b3JrX2lkYf+xDQoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:red_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSAAwAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZF9jb25jcmV0ZQQJAG5hbWVfaGFzaPWmNowLGubqAwoAbmV0d29ya19pZKwyx58KBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:orange_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRzAwAACAQAbmFtZRkAbWluZWNyYWZ0Om9yYW5nZV9jb25jcmV0ZQQJAG5hbWVfaGFzaAgE8XmaAi6+AwoAbmV0d29ya19pZMDQNz8KBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:yellow_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR2AwAACAQAbmFtZRkAbWluZWNyYWZ0OnllbGxvd19jb25jcmV0ZQQJAG5hbWVfaGFzaE6ONfJPBd0+AwoAbmV0d29ya19pZMarutwKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:lime_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR3AwAACAQAbmFtZRcAbWluZWNyYWZ0OmxpbWVfY29uY3JldGUECQBuYW1lX2hhc2gnd8JW6wmJcAMKAG5ldHdvcmtfaWTd47aoCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:green_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR/AwAACAQAbmFtZRgAbWluZWNyYWZ0OmdyZWVuX2NvbmNyZXRlBAkAbmFtZV9oYXNokbFxRKchQZkDCgBuZXR3b3JrX2lkmhZWUgoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:cyan_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR7AwAACAQAbmFtZRcAbWluZWNyYWZ0OmN5YW5fY29uY3JldGUECQBuYW1lX2hhc2hFRrWJ33qj1wMKAG5ldHdvcmtfaWQbi5b8CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:light_blue_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR1AwAACAQAbmFtZR0AbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY29uY3JldGUECQBuYW1lX2hhc2gHAe0kl0SE4AMKAG5ldHdvcmtfaWRL/GbSCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:blue_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR9AwAACAQAbmFtZRcAbWluZWNyYWZ0OmJsdWVfY29uY3JldGUECQBuYW1lX2hhc2hiay301nnj1wMKAG5ldHdvcmtfaWRMvFXNCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:purple_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR8AwAACAQAbmFtZRkAbWluZWNyYWZ0OnB1cnBsZV9jb25jcmV0ZQQJAG5hbWVfaGFzaHBHflsPIwdXAwoAbmV0d29ya19pZCyKA5gKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:magenta_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR0AwAACAQAbmFtZRoAbWluZWNyYWZ0Om1hZ2VudGFfY29uY3JldGUECQBuYW1lX2hhc2gN7LuB/OvdZAMKAG5ldHdvcmtfaWTc6ZOdCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:pink_concrete", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR4AwAACAQAbmFtZRcAbWluZWNyYWZ0OnBpbmtfY29uY3JldGUECQBuYW1lX2hhc2ii2G5F0u3SOAMKAG5ldHdvcmtfaWSszGgrCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:clay", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRSAAAACAQAbmFtZQ4AbWluZWNyYWZ0OmNsYXkECQBuYW1lX2hhc2j/S6sKXRcpzwMKAG5ldHdvcmtfaWRmsb8nCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:hardened_clay", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSsAAAACAQAbmFtZRcAbWluZWNyYWZ0OmhhcmRlbmVkX2NsYXkECQBuYW1lX2hhc2jrnRwCJ0krJAMKAG5ldHdvcmtfaWRBCOrrCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:white_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSfAAAACAQAbmFtZRoAbWluZWNyYWZ0OndoaXRlX3RlcnJhY290dGEECQBuYW1lX2hhc2j3RSdgmnAIewMKAG5ldHdvcmtfaWSimKw+CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:light_gray_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAwAACAQAbmFtZR8AbWluZWNyYWZ0OmxpZ2h0X2dyYXlfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAz1Ri3wIxomAwoAbmV0d29ya19pZH5qgOcKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:gray_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTZAwAACAQAbmFtZRkAbWluZWNyYWZ0OmdyYXlfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAXdSLAaNZ9vAwoAbmV0d29ya19pZM1QDV0KBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:black_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWThAwAACAQAbmFtZRoAbWluZWNyYWZ0OmJsYWNrX3RlcnJhY290dGEECQBuYW1lX2hhc2jxssdv5vlbpgMKAG5ldHdvcmtfaWRE3Ru/CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:brown_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTeAwAACAQAbmFtZRoAbWluZWNyYWZ0OmJyb3duX3RlcnJhY290dGEECQBuYW1lX2hhc2gG4kPenmOF9gMKAG5ldHdvcmtfaWQ/i0iNCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:red_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAwAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNo7fX56HXFejEDCgBuZXR3b3JrX2lk8tTF8QoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:orange_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAwAACAQAbmFtZRsAbWluZWNyYWZ0Om9yYW5nZV90ZXJyYWNvdHRhBAkAbmFtZV9oYXNo0Hjmql3sruMDCgBuZXR3b3JrX2lklmqmkAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:yellow_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTWAwAACAQAbmFtZRsAbWluZWNyYWZ0OnllbGxvd190ZXJyYWNvdHRhBAkAbmFtZV9oYXNoqkyKKrmA3VcDCgBuZXR3b3JrX2lkaM/orAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:lime_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAwAACAQAbmFtZRkAbWluZWNyYWZ0OmxpbWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaANjADFOF9v7AwoAbmV0d29ya19pZJt0XsgKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:green_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAwAACAQAbmFtZRoAbWluZWNyYWZ0OmdyZWVuX3RlcnJhY290dGEECQBuYW1lX2hhc2j5Ybq36yYwRQMKAG5ldHdvcmtfaWQ8kGdHCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:cyan_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTbAwAACAQAbmFtZRkAbWluZWNyYWZ0OmN5YW5fdGVycmFjb3R0YQQJAG5hbWVfaGFzaN09COzMuHwAAwoAbmV0d29ya19pZIWPCzoKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:light_blue_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTVAwAACAQAbmFtZR8AbWluZWNyYWZ0OmxpZ2h0X2JsdWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaOMytez7cOZiAwoAbmV0d29ya19pZFHK1UsKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:blue_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAwAACAQAbmFtZRkAbWluZWNyYWZ0OmJsdWVfdGVycmFjb3R0YQQJAG5hbWVfaGFzaF6inyTK5RpAAwoAbmV0d29ya19pZF5mVZIKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:purple_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAwAACAQAbmFtZRsAbWluZWNyYWZ0OnB1cnBsZV90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoKF7YG61yTbEDCgBuZXR3b3JrX2lkhtRDlwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:magenta_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTUAwAACAQAbmFtZRwAbWluZWNyYWZ0Om1hZ2VudGFfdGVycmFjb3R0YQQJAG5hbWVfaGFzaLWvtpAVtztyAwoAbmV0d29ya19pZN5SoakKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:pink_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTYAwAACAQAbmFtZRkAbWluZWNyYWZ0OnBpbmtfdGVycmFjb3R0YQQJAG5hbWVfaGFzaJ7mzvyzSQZTAwoAbmV0d29ya19pZDJWe4YKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:white_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAAAACAQAbmFtZSEAbWluZWNyYWZ0OndoaXRlX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoiVzCdoHAJo0DCgBuZXR3b3JrX2lkIlj9AAoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:silver_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAAAACAQAbmFtZSIAbWluZWNyYWZ0OnNpbHZlcl9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaAVsA0CnhzA4AwoAbmV0d29ya19pZPnxtJEKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:gray_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAAAACAQAbmFtZSAAbWluZWNyYWZ0OmdyYXlfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2jvLZt9u/lF/AMKAG5ldHdvcmtfaWQVU8eFCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:black_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTrAAAACAQAbmFtZSEAbWluZWNyYWZ0OmJsYWNrX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoe8I4xAXbO5UDCgBuZXR3b3JrX2lk2Icb9AoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:brown_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWToAAAACAQAbmFtZSEAbWluZWNyYWZ0OmJyb3duX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNoSiNZOobbpjoDCgBuZXR3b3JrX2lkJy0jwgoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:red_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTqAAAACAQAbmFtZR8AbWluZWNyYWZ0OnJlZF9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaBdWFGLmCLFVAwoAbmV0d29ya19pZMYBJSEKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:orange_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTdAAAACAQAbmFtZSIAbWluZWNyYWZ0Om9yYW5nZV9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaMyJMrnPr7szAwoAbmV0d29ya19pZN6+7TUKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:yellow_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAAAACAQAbmFtZSIAbWluZWNyYWZ0OnllbGxvd19nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaN6NaIhf6m0uAwoAbmV0d29ya19pZKRHXeoKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:lime_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWThAAAACAQAbmFtZSAAbWluZWNyYWZ0OmxpbWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2iF3E68/rB2EAMKAG5ldHdvcmtfaWSP7qQWCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:green_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTpAAAACAQAbmFtZSEAbWluZWNyYWZ0OmdyZWVuX2dsYXplZF90ZXJyYWNvdHRhBAkAbmFtZV9oYXNow5mo8aQDFboDCgBuZXR3b3JrX2lkoF11kgoGAHN0YXRlcwMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:cyan_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAAAACAQAbmFtZSAAbWluZWNyYWZ0OmN5YW5fZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2gnNB+cCFRJhwMKAG5ldHdvcmtfaWT9buMtCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:light_blue_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAAAACAQAbmFtZSYAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2gladnCDBKCigMKAG5ldHdvcmtfaWS5CszFCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:blue_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTnAAAACAQAbmFtZSAAbWluZWNyYWZ0OmJsdWVfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2giOZK+2nB1igMKAG5ldHdvcmtfaWR+e22CCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:purple_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTbAAAACAQAbmFtZSIAbWluZWNyYWZ0OnB1cnBsZV9nbGF6ZWRfdGVycmFjb3R0YQQJAG5hbWVfaGFzaIQU03txeAfHAwoAbmV0d29ya19pZLKbSE4KBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:magenta_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTeAAAACAQAbmFtZSMAbWluZWNyYWZ0Om1hZ2VudGFfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2i/SNqDJbfjMgMKAG5ldHdvcmtfaWQKf9UvCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:pink_glazed_terracotta", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAAAACAQAbmFtZSAAbWluZWNyYWZ0OnBpbmtfZ2xhemVkX3RlcnJhY290dGEECQBuYW1lX2hhc2hik8DVt4g+twMKAG5ldHdvcmtfaWTKzav2CgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:purpur_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAAAACAQAbmFtZRYAbWluZWNyYWZ0OnB1cnB1cl9ibG9jawQJAG5hbWVfaGFzaAgLwnUZGlzsAwoAbmV0d29ya19pZGCZ+4UKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:purpur_pillar", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS2BAAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnB1cl9waWxsYXIECQBuYW1lX2hhc2iFcSsdykO+jgMKAG5ldHdvcmtfaWQe0+geCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:packed_mud", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTcAgAACAQAbmFtZRQAbWluZWNyYWZ0OnBhY2tlZF9tdWQECQBuYW1lX2hhc2gHOMa121h4FgMKAG5ldHdvcmtfaWTUb6LyCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:mud_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAgAACAQAbmFtZRQAbWluZWNyYWZ0Om11ZF9icmlja3MECQBuYW1lX2hhc2iDL/SVl/PewQMKAG5ldHdvcmtfaWSkBjaDCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:nether_wart_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTWAAAACAQAbmFtZRsAbWluZWNyYWZ0Om5ldGhlcl93YXJ0X2Jsb2NrBAkAbmFtZV9oYXNo9XGS4GNnlV4DCgBuZXR3b3JrX2lkh3apIgoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:warped_wart_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAQAACAQAbmFtZRsAbWluZWNyYWZ0OndhcnBlZF93YXJ0X2Jsb2NrBAkAbmFtZV9oYXNo9IqDS9yUPJoDCgBuZXR3b3JrX2lkMpKAbAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:shroomlight", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTlAQAACAQAbmFtZRUAbWluZWNyYWZ0OnNocm9vbWxpZ2h0BAkAbmFtZV9oYXNoZHCHcHX/HYADCgBuZXR3b3JrX2lkLG2JiwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:crimson_nylium", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTnAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fbnlsaXVtBAkAbmFtZV9oYXNoOr6DJYW2bFYDCgBuZXR3b3JrX2lkuWpRDgoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:warped_nylium", + "block_state_b64": "CgAAAwgAYmxvY2tfaWToAQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9ueWxpdW0ECQBuYW1lX2hhc2g0Zf89cfr3rwMKAG5ldHdvcmtfaWSu/kekCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:netherrack", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRXAAAACAQAbmFtZRQAbWluZWNyYWZ0Om5ldGhlcnJhY2sECQBuYW1lX2hhc2i/r5ZyRsvPyQMKAG5ldHdvcmtfaWTAiTOACgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:basalt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTpAQAACAQAbmFtZRAAbWluZWNyYWZ0OmJhc2FsdAQJAG5hbWVfaGFzaH+UQO2yWodiAwoAbmV0d29ya19pZBPNSV4KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:polished_basalt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTqAQAACAQAbmFtZRkAbWluZWNyYWZ0OnBvbGlzaGVkX2Jhc2FsdAQJAG5hbWVfaGFzaMS+L0gMnRcBAwoAbmV0d29ya19pZF+/mHwKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:smooth_basalt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR4AgAACAQAbmFtZRcAbWluZWNyYWZ0OnNtb290aF9iYXNhbHQECQBuYW1lX2hhc2jKPUdz89kuNAMKAG5ldHdvcmtfaWTkb/oVCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:soul_soil", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTrAQAACAQAbmFtZRMAbWluZWNyYWZ0OnNvdWxfc29pbAQJAG5hbWVfaGFzaC1/87ccutuTAwoAbmV0d29ya19pZKc63SMKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:dirt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAAAACAQAbmFtZQ4AbWluZWNyYWZ0OmRpcnQECQBuYW1lX2hhc2hXp6jnXAe+kQMKAG5ldHdvcmtfaWSG706CCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:coarse_dirt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTBBAAACAQAbmFtZRUAbWluZWNyYWZ0OmNvYXJzZV9kaXJ0BAkAbmFtZV9oYXNosd+cah7WSmoDCgBuZXR3b3JrX2lkgS5RcAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:farmland", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ8AAAACAQAbmFtZRIAbWluZWNyYWZ0OmZhcm1sYW5kBAkAbmFtZV9oYXNoxyQ5ag7LolADCgBuZXR3b3JrX2lkX618FQoGAHN0YXRlcwMSAG1vaXN0dXJpemVkX2Ftb3VudAAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:grass_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQCAAAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXNzX2Jsb2NrBAkAbmFtZV9oYXNojPyGp3/CSZwDCgBuZXR3b3JrX2lktCgx3goGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:grass_path", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTGAAAACAQAbmFtZRQAbWluZWNyYWZ0OmdyYXNzX3BhdGgECQBuYW1lX2hhc2i0/KZV8Qsy+gMKAG5ldHdvcmtfaWT7CcdzCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:podzol", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTzAAAACAQAbmFtZRAAbWluZWNyYWZ0OnBvZHpvbAQJAG5hbWVfaGFzaBzqokRjH4Z1AwoAbmV0d29ya19pZPPS/GUKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:mycelium", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRuAAAACAQAbmFtZRIAbWluZWNyYWZ0Om15Y2VsaXVtBAkAbmFtZV9oYXNojTN09cKickIDCgBuZXR3b3JrX2lkLNPxXQoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:mud", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTYAgAACAQAbmFtZQ0AbWluZWNyYWZ0Om11ZAQJAG5hbWVfaGFzaPb/3P+uLy+9AwoAbmV0d29ya19pZPIUlUkKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:stone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAAAACAQAbmFtZQ8AbWluZWNyYWZ0OnN0b25lBAkAbmFtZV9oYXNoE3mqhJxzJycDCgBuZXR3b3JrX2lkIQ4xgAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:iron_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQPAAAACAQAbmFtZRIAbWluZWNyYWZ0Omlyb25fb3JlBAkAbmFtZV9oYXNoS7BYtLnfx3gDCgBuZXR3b3JrX2lk3loneQoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:gold_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQOAAAACAQAbmFtZRIAbWluZWNyYWZ0OmdvbGRfb3JlBAkAbmFtZV9oYXNoC5Y+DUGXLC4DCgBuZXR3b3JrX2lkNhvMfwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:diamond_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ4AAAACAQAbmFtZRUAbWluZWNyYWZ0OmRpYW1vbmRfb3JlBAkAbmFtZV9oYXNokUOJ2wZZrGQDCgBuZXR3b3JrX2lk/dChVAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:lapis_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQVAAAACAQAbmFtZRMAbWluZWNyYWZ0OmxhcGlzX29yZQQJAG5hbWVfaGFzaMrmrUrSzb7qAwoAbmV0d29ya19pZMg+qK4KBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:redstone_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRJAAAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZHN0b25lX29yZQQJAG5hbWVfaGFzaFHVnp8Wc4JbAwoAbmV0d29ya19pZKDYvQoKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:coal_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQQAAAACAQAbmFtZRIAbWluZWNyYWZ0OmNvYWxfb3JlBAkAbmFtZV9oYXNo1OjA+Iuy51oDCgBuZXR3b3JrX2lk+R/aKAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:copper_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ2AgAACAQAbmFtZRQAbWluZWNyYWZ0OmNvcHBlcl9vcmUECQBuYW1lX2hhc2iSZduSntOzOwMKAG5ldHdvcmtfaWQtIuCnCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:emerald_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAAAACAQAbmFtZRUAbWluZWNyYWZ0OmVtZXJhbGRfb3JlBAkAbmFtZV9oYXNoJTovr+VgINsDCgBuZXR3b3JrX2lknbkqCgoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:quartz_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSZAAAACAQAbmFtZRQAbWluZWNyYWZ0OnF1YXJ0el9vcmUECQBuYW1lX2hhc2g0yNHLMK9TaQMKAG5ldHdvcmtfaWSzN7nzCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:nether_gold_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQfAgAACAQAbmFtZRkAbWluZWNyYWZ0Om5ldGhlcl9nb2xkX29yZQQJAG5hbWVfaGFzaEJZ7segIBgBAwoAbmV0d29ya19pZNI9pDgKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:ancient_debris", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQOAgAACAQAbmFtZRgAbWluZWNyYWZ0OmFuY2llbnRfZGVicmlzBAkAbmFtZV9oYXNoNrbxMc9AwKcDCgBuZXR3b3JrX2lkrSNjEAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:deepslate_iron_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSQAgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9pcm9uX29yZQQJAG5hbWVfaGFzaB/fDL9pgvXXAwoAbmV0d29ya19pZFA0bz4KBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:deepslate_gold_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9nb2xkX29yZQQJAG5hbWVfaGFzaF9G7WYhKFinAwoAbmV0d29ya19pZHQTfBUKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:deepslate_diamond_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSUAgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV9kaWFtb25kX29yZQQJAG5hbWVfaGFzaEUH5USh+iD3AwoAbmV0d29ya19pZHP6VzAKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:deepslate_lapis_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAgAACAQAbmFtZR0AbWluZWNyYWZ0OmRlZXBzbGF0ZV9sYXBpc19vcmUECQBuYW1lX2hhc2j+yFxU/KZs1gMKAG5ldHdvcmtfaWRKINzICgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:deepslate_redstone_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSSAgAACAQAbmFtZSAAbWluZWNyYWZ0OmRlZXBzbGF0ZV9yZWRzdG9uZV9vcmUECQBuYW1lX2hhc2iVgM3wWWD6ugMKAG5ldHdvcmtfaWReBdYRCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:deepslate_emerald_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSWAgAACAQAbmFtZR8AbWluZWNyYWZ0OmRlZXBzbGF0ZV9lbWVyYWxkX29yZQQJAG5hbWVfaGFzaNlfo5HTwS6wAwoAbmV0d29ya19pZNeie6sKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:deepslate_coal_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSVAgAACAQAbmFtZRwAbWluZWNyYWZ0OmRlZXBzbGF0ZV9jb2FsX29yZQQJAG5hbWVfaGFzaIjikmcbRrPPAwoAbmV0d29ya19pZD9TiygKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:deepslate_copper_ore", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSXAgAACAQAbmFtZR4AbWluZWNyYWZ0OmRlZXBzbGF0ZV9jb3BwZXJfb3JlBAkAbmFtZV9oYXNottjV4Ev5LAQDCgBuZXR3b3JrX2lkP23rgQoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:gravel", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQNAAAACAQAbmFtZRAAbWluZWNyYWZ0OmdyYXZlbAQJAG5hbWVfaGFzaOFxz8XJd2r/AwoAbmV0d29ya19pZBpfI1sKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:granite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRNAwAACAQAbmFtZREAbWluZWNyYWZ0OmdyYW5pdGUECQBuYW1lX2hhc2iq+Dur2pw4AwMKAG5ldHdvcmtfaWT2NMfJCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:diorite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRPAwAACAQAbmFtZREAbWluZWNyYWZ0OmRpb3JpdGUECQBuYW1lX2hhc2iaFsq2iinZBQMKAG5ldHdvcmtfaWQqGE6XCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:andesite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRRAwAACAQAbmFtZRIAbWluZWNyYWZ0OmFuZGVzaXRlBAkAbmFtZV9oYXNosaLIEnQQoSYDCgBuZXR3b3JrX2lkEApRZAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:blackstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQQAgAACAQAbmFtZRQAbWluZWNyYWZ0OmJsYWNrc3RvbmUECQBuYW1lX2hhc2iMFYziD80D6QMKAG5ldHdvcmtfaWSrUryHCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR5AgAACAQAbmFtZRMAbWluZWNyYWZ0OmRlZXBzbGF0ZQQJAG5hbWVfaGFzaKX5pAblxz8TAwoAbmV0d29ya19pZOJoQjsKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:polished_granite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWROAwAACAQAbmFtZRoAbWluZWNyYWZ0OnBvbGlzaGVkX2dyYW5pdGUECQBuYW1lX2hhc2iLiEfys8pFIAMKAG5ldHdvcmtfaWTCxxcHCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:polished_diorite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRQAwAACAQAbmFtZRoAbWluZWNyYWZ0OnBvbGlzaGVkX2Rpb3JpdGUECQBuYW1lX2hhc2hTxY4fKmNmlAMKAG5ldHdvcmtfaWTmtjdRCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:polished_andesite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRSAwAACAQAbmFtZRsAbWluZWNyYWZ0OnBvbGlzaGVkX2FuZGVzaXRlBAkAbmFtZV9oYXNovl28uFk4HuQDCgBuZXR3b3JrX2lklFjuCwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:polished_blackstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQiAgAACAQAbmFtZR0AbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmUECQBuYW1lX2hhc2jT9fHCl6vWQQMKAG5ldHdvcmtfaWR/Ho6oCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:polished_deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR+AgAACAQAbmFtZRwAbWluZWNyYWZ0OnBvbGlzaGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaHC1edoaWF3uAwoAbmV0d29ya19pZCPeQsEKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:sand", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQMAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnNhbmQECQBuYW1lX2hhc2i6lthXXbAyWAMKAG5ldHdvcmtfaWRjeUMICgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:red_sand", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS0BAAACAQAbmFtZRIAbWluZWNyYWZ0OnJlZF9zYW5kBAkAbmFtZV9oYXNoCiarI69JQCkDCgBuZXR3b3JrX2lkU8UD/AoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:cactus", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRRAAAACAQAbmFtZRAAbWluZWNyYWZ0OmNhY3R1cwQJAG5hbWVfaGFzaCG9zL0N4wvGAwoAbmV0d29ya19pZDeCERAKBgBzdGF0ZXMDAwBhZ2UAAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:oak_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQRAAAACAQAbmFtZREAbWluZWNyYWZ0Om9ha19sb2cECQBuYW1lX2hhc2ho6TS+K7PZFQMKAG5ldHdvcmtfaWQjfjoxCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:stripped_oak_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQJAQAACAQAbmFtZRoAbWluZWNyYWZ0OnN0cmlwcGVkX29ha19sb2cECQBuYW1lX2hhc2h8dqh+OOHU4wMKAG5ldHdvcmtfaWSYKjdrCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:spruce_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ4AwAACAQAbmFtZRQAbWluZWNyYWZ0OnNwcnVjZV9sb2cECQBuYW1lX2hhc2hZ03qaLoF3WgMKAG5ldHdvcmtfaWRlFD8eCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:stripped_spruce_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQEAQAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX3NwcnVjZV9sb2cECQBuYW1lX2hhc2iNrhKjS5IyrgMKAG5ldHdvcmtfaWRQcEC3CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:birch_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ5AwAACAQAbmFtZRMAbWluZWNyYWZ0OmJpcmNoX2xvZwQJAG5hbWVfaGFzaBUzT3NxsZAnAwoAbmV0d29ya19pZBKN3VQKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:stripped_birch_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQFAQAACAQAbmFtZRwAbWluZWNyYWZ0OnN0cmlwcGVkX2JpcmNoX2xvZwQJAG5hbWVfaGFzaCFKS4AeuSidAwoAbmV0d29ya19pZN0IONIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:jungle_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ6AwAACAQAbmFtZRQAbWluZWNyYWZ0Omp1bmdsZV9sb2cECQBuYW1lX2hhc2gkwW0KNulqDgMKAG5ldHdvcmtfaWQaziU/CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:stripped_jungle_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAQAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2p1bmdsZV9sb2cECQBuYW1lX2hhc2hAwMsgOk02JAMKAG5ldHdvcmtfaWQvls0eCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:acacia_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAAAACAQAbmFtZRQAbWluZWNyYWZ0OmFjYWNpYV9sb2cECQBuYW1lX2hhc2iV48VpYhjoYQMKAG5ldHdvcmtfaWRxEqe0CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:stripped_acacia_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAQAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2FjYWNpYV9sb2cECQBuYW1lX2hhc2hJb0lQqnEqlgMKAG5ldHdvcmtfaWRg3IdRCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:dark_oak_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ7AwAACAQAbmFtZRYAbWluZWNyYWZ0OmRhcmtfb2FrX2xvZwQJAG5hbWVfaGFzaIWfVRd0XUo3AwoAbmV0d29ya19pZPMM7LYKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:stripped_dark_oak_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQIAQAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2Rhcmtfb2FrX2xvZwQJAG5hbWVfaGFzaPFTdxRdPwkOAwoAbmV0d29ya19pZDIzenIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:mangrove_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAgAACAQAbmFtZRYAbWluZWNyYWZ0Om1hbmdyb3ZlX2xvZwQJAG5hbWVfaGFzaHZe6DzPZBobAwoAbmV0d29ya19pZG6DuYkKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:stripped_mangrove_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAgAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX21hbmdyb3ZlX2xvZwQJAG5hbWVfaGFzaLqIBo4hwA//AwoAbmV0d29ya19pZPtRn7UKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:cherry_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQXAwAACAQAbmFtZRQAbWluZWNyYWZ0OmNoZXJyeV9sb2cECQBuYW1lX2hhc2hwFlaioppB1wMKAG5ldHdvcmtfaWS2sdXECgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:stripped_cherry_log", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQWAwAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2NoZXJyeV9sb2cECQBuYW1lX2hhc2i85H6G+WhXaAMKAG5ldHdvcmtfaWRjzoglCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:crimson_stem", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTgAQAACAQAbmFtZRYAbWluZWNyYWZ0OmNyaW1zb25fc3RlbQQJAG5hbWVfaGFzaM0FzfL0UTKZAwoAbmV0d29ya19pZKvzID0KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:stripped_crimson_stem", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTvAQAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2NyaW1zb25fc3RlbQQJAG5hbWVfaGFzaDlA6nood57EAwoAbmV0d29ya19pZHrIqjIKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:warped_stem", + "block_state_b64": "CgAAAwgAYmxvY2tfaWThAQAACAQAbmFtZRUAbWluZWNyYWZ0OndhcnBlZF9zdGVtBAkAbmFtZV9oYXNon7cKfPZxdrUDCgBuZXR3b3JrX2lkerWyMwoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:stripped_warped_stem", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTwAQAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX3dhcnBlZF9zdGVtBAkAbmFtZV9oYXNoEw+y0dDPSd8DCgBuZXR3b3JrX2lkIQ9vBAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:oak_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAQAACAQAbmFtZRIAbWluZWNyYWZ0Om9ha193b29kBAkAbmFtZV9oYXNoqQIkuVPyJX0DCgBuZXR3b3JrX2lku2G1YAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:stripped_oak_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQyBAAACAQAbmFtZRsAbWluZWNyYWZ0OnN0cmlwcGVkX29ha193b29kBAkAbmFtZV9oYXNovW6KCv+VZnsDCgBuZXR3b3JrX2lkkhWGegoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:spruce_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQtBAAACAQAbmFtZRUAbWluZWNyYWZ0OnNwcnVjZV93b29kBAkAbmFtZV9oYXNoTrIJ5TAQ+OgDCgBuZXR3b3JrX2lkaXLxCwoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:stripped_spruce_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQzBAAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX3NwcnVjZV93b29kBAkAbmFtZV9oYXNoMnuUk4Xo6icDCgBuZXR3b3JrX2lkes2ydAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:birch_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQuBAAACAQAbmFtZRQAbWluZWNyYWZ0OmJpcmNoX3dvb2QECQBuYW1lX2hhc2iqVjG4xt0cKQMKAG5ldHdvcmtfaWS06c5VCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:stripped_birch_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ0BAAACAQAbmFtZR0AbWluZWNyYWZ0OnN0cmlwcGVkX2JpcmNoX3dvb2QECQBuYW1lX2hhc2hm88R604TKbAMKAG5ldHdvcmtfaWRleEMJCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:jungle_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQvBAAACAQAbmFtZRUAbWluZWNyYWZ0Omp1bmdsZV93b29kBAkAbmFtZV9oYXNo9bYW29ORWCoDCgBuZXR3b3JrX2lkyFyKLQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:stripped_jungle_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ1BAAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX2p1bmdsZV93b29kBAkAbmFtZV9oYXNoUVs6KsZQRBoDCgBuZXR3b3JrX2lk92k8HQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:acacia_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQwBAAACAQAbmFtZRUAbWluZWNyYWZ0OmFjYWNpYV93b29kBAkAbmFtZV9oYXNoKkDfgzlJUcIDCgBuZXR3b3JrX2lkuTWlcgoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:stripped_acacia_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ2BAAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX2FjYWNpYV93b29kBAkAbmFtZV9oYXNo/kOPN2bCJhUDCgBuZXR3b3JrX2lktl6LwQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:dark_oak_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQxBAAACAQAbmFtZRcAbWluZWNyYWZ0OmRhcmtfb2FrX3dvb2QECQBuYW1lX2hhc2jaKv4ORLadAAMKAG5ldHdvcmtfaWSDrNQ8CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:stripped_dark_oak_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ3BAAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX2Rhcmtfb2FrX3dvb2QECQBuYW1lX2hhc2h2jFDfKVFgfAMKAG5ldHdvcmtfaWTgZQ5VCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:mangrove_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTwAgAACAQAbmFtZRcAbWluZWNyYWZ0Om1hbmdyb3ZlX3dvb2QECQBuYW1lX2hhc2iXVxG0JG2fVAMKAG5ldHdvcmtfaWTok1JCCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkBDABzdHJpcHBlZF9iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:stripped_mangrove_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTxAgAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX21hbmdyb3ZlX3dvb2QECQBuYW1lX2hhc2h7CkbaBF7/WAMKAG5ldHdvcmtfaWQLAX88CgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:cherry_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQhAwAACAQAbmFtZRUAbWluZWNyYWZ0OmNoZXJyeV93b29kBAkAbmFtZV9oYXNoAW8srlmpBM8DCgBuZXR3b3JrX2lkEALMfAoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AQwAc3RyaXBwZWRfYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:stripped_cherry_wood", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQgAwAACAQAbmFtZR4AbWluZWNyYWZ0OnN0cmlwcGVkX2NoZXJyeV93b29kBAkAbmFtZV9oYXNo/e7KXv+CB38DCgBuZXR3b3JrX2lkg5aVtQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:crimson_hyphae", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQqAgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25faHlwaGFlBAkAbmFtZV9oYXNouRmKmfSqEWADCgBuZXR3b3JrX2lk+Tm5rQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:stripped_crimson_hyphae", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQrAgAACAQAbmFtZSEAbWluZWNyYWZ0OnN0cmlwcGVkX2NyaW1zb25faHlwaGFlBAkAbmFtZV9oYXNoFffwmABq4LUDCgBuZXR3b3JrX2lkZAlUbgoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:warped_hyphae", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQpAgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9oeXBoYWUECQBuYW1lX2hhc2hn8plQUr6pmQMKAG5ldHdvcmtfaWRU2AIBCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:stripped_warped_hyphae", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQsAgAACAQAbmFtZSAAbWluZWNyYWZ0OnN0cmlwcGVkX3dhcnBlZF9oeXBoYWUECQBuYW1lX2hhc2irKq+HYPSgjQMKAG5ldHdvcmtfaWSbrOPDCgYAc3RhdGVzCAsAcGlsbGFyX2F4aXMBAHkAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:bamboo_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQOAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJhbWJvb19ibG9jawQJAG5hbWVfaGFzaAbDeur6stIBAwoAbmV0d29ya19pZCJAwn0KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:stripped_bamboo_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQPAwAACAQAbmFtZR8AbWluZWNyYWZ0OnN0cmlwcGVkX2JhbWJvb19ibG9jawQJAG5hbWVfaGFzaJpwytpZOZM9AwoAbmV0d29ya19pZKuRbNEKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:oak_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQSAAAACAQAbmFtZRQAbWluZWNyYWZ0Om9ha19sZWF2ZXMECQBuYW1lX2hhc2h6O4xGqA2oKgMKAG5ldHdvcmtfaWT98c59CgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:spruce_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQfBAAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9sZWF2ZXMECQBuYW1lX2hhc2i9x1CtNAuqZwMKAG5ldHdvcmtfaWSzF7pTCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:birch_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQgBAAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX2xlYXZlcwQJAG5hbWVfaGFzaBlAGHaoaLZSAwoAbmV0d29ya19pZOjtvWcKBgBzdGF0ZXMBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:jungle_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQhBAAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9sZWF2ZXMECQBuYW1lX2hhc2iW1uAH07zGhgMKAG5ldHdvcmtfaWSA5KX0CgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:acacia_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAAAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9sZWF2ZXMECQBuYW1lX2hhc2iZJf8dAgDRNQMKAG5ldHdvcmtfaWQ/G7VuCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:dark_oak_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQiBAAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX2xlYXZlcwQJAG5hbWVfaGFzaCk7rDipWFSjAwoAbmV0d29ya19pZJ2AkbYKBgBzdGF0ZXMBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:mangrove_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX2xlYXZlcwQJAG5hbWVfaGFzaKyI/dWvhEG8AwoAbmV0d29ya19pZPQxCZ8KBgBzdGF0ZXMBDgBwZXJzaXN0ZW50X2JpdAABCgB1cGRhdGVfYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:cherry_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQjAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9sZWF2ZXMECQBuYW1lX2hhc2giTs9ChhYBlQMKAG5ldHdvcmtfaWR8bPpwCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:azalea_leaves", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRDAgAACAQAbmFtZRcAbWluZWNyYWZ0OmF6YWxlYV9sZWF2ZXMECQBuYW1lX2hhc2iXFhD57wFS7AMKAG5ldHdvcmtfaWTNB/9ECgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:azalea_leaves_flowered", + "block_state_b64": "CgAAAwgAYmxvY2tfaWREAgAACAQAbmFtZSAAbWluZWNyYWZ0OmF6YWxlYV9sZWF2ZXNfZmxvd2VyZWQECQBuYW1lX2hhc2gs8jxlS/pMrwMKAG5ldHdvcmtfaWQ7W4PyCgYAc3RhdGVzAQ4AcGVyc2lzdGVudF9iaXQAAQoAdXBkYXRlX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:oak_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAAAACAQAbmFtZRUAbWluZWNyYWZ0Om9ha19zYXBsaW5nBAkAbmFtZV9oYXNoogXcT9QfjiUDCgBuZXR3b3JrX2lkG22C+AoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:spruce_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ4BAAACAQAbmFtZRgAbWluZWNyYWZ0OnNwcnVjZV9zYXBsaW5nBAkAbmFtZV9oYXNoe8hz4uYP0FcDCgBuZXR3b3JrX2lkUQmhaQoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:birch_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ5BAAACAQAbmFtZRcAbWluZWNyYWZ0OmJpcmNoX3NhcGxpbmcECQBuYW1lX2hhc2h348iJQ/tK4wMKAG5ldHdvcmtfaWQ2Uh53CgYAc3RhdGVzAQcAYWdlX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:jungle_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ6BAAACAQAbmFtZRgAbWluZWNyYWZ0Omp1bmdsZV9zYXBsaW5nBAkAbmFtZV9oYXNo7tyTOdSrxaADCgBuZXR3b3JrX2lkXmBAdAoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:acacia_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ7BAAACAQAbmFtZRgAbWluZWNyYWZ0OmFjYWNpYV9zYXBsaW5nBAkAbmFtZV9oYXNo99sg15uoX7ADCgBuZXR3b3JrX2lkPXX1KgoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:dark_oak_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ8BAAACAQAbmFtZRoAbWluZWNyYWZ0OmRhcmtfb2FrX3NhcGxpbmcECQBuYW1lX2hhc2jnVzFplW7cHgMKAG5ldHdvcmtfaWTD4giHCgYAc3RhdGVzAQcAYWdlX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:mangrove_propagule", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTZAgAACAQAbmFtZRwAbWluZWNyYWZ0Om1hbmdyb3ZlX3Byb3BhZ3VsZQQJAG5hbWVfaGFzaJGeox6hkfLFAwoAbmV0d29ya19pZAIpvpYKBgBzdGF0ZXMBBwBoYW5naW5nAAMPAHByb3BhZ3VsZV9zdGFnZQAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:cherry_sapling", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQiAwAACAQAbmFtZRgAbWluZWNyYWZ0OmNoZXJyeV9zYXBsaW5nBAkAbmFtZV9oYXNoGrPpNMf1LtcDCgBuZXR3b3JrX2lkypakXQoGAHN0YXRlcwEHAGFnZV9iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:bee_nest", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTZAQAACAQAbmFtZRIAbWluZWNyYWZ0OmJlZV9uZXN0BAkAbmFtZV9oYXNo2R2WBxUHEZIDCgBuZXR3b3JrX2lkiXWLEAoGAHN0YXRlcwMJAGRpcmVjdGlvbgAAAAADCwBob25leV9sZXZlbAAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "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": "CgAAAwgAYmxvY2tfaWRnAAAACAQAbmFtZRUAbWluZWNyYWZ0Om1lbG9uX2Jsb2NrBAkAbmFtZV9oYXNoXxSm0iYpAx8DCgBuZXR3b3JrX2lkC9rqygoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:melon_slice" + }, + { + "id": "minecraft:glistering_melon_slice" + }, + { + "id": "minecraft:sweet_berries" + }, + { + "id": "minecraft:glow_berries" + }, + { + "id": "minecraft:pumpkin", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRWAAAACAQAbmFtZREAbWluZWNyYWZ0OnB1bXBraW4ECQBuYW1lX2hhc2gc8A3jaSzWbgMKAG5ldHdvcmtfaWRFGA+xCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:carved_pumpkin", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSaAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNhcnZlZF9wdW1wa2luBAkAbmFtZV9oYXNoPu1T0MJuG90DCgBuZXR3b3JrX2lkXNNn5QoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:lit_pumpkin", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRbAAAACAQAbmFtZRUAbWluZWNyYWZ0OmxpdF9wdW1wa2luBAkAbmFtZV9oYXNo7gWtEm2uPL0DCgBuZXR3b3JrX2lki8sU4AoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:honeycomb" + }, + { + "id": "minecraft:fern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRPBAAACAQAbmFtZQ4AbWluZWNyYWZ0OmZlcm4ECQBuYW1lX2hhc2iHbj3yXFn4owMKAG5ldHdvcmtfaWQKC6u7CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:large_fern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRgBAAACAQAbmFtZRQAbWluZWNyYWZ0OmxhcmdlX2Zlcm4ECQBuYW1lX2hhc2gnE9sd0LzHtQMKAG5ldHdvcmtfaWTS9hG4CgYAc3RhdGVzAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:short_grass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQfAAAACAQAbmFtZRUAbWluZWNyYWZ0OnNob3J0X2dyYXNzBAkAbmFtZV9oYXNobWQghLH0bLcDCgBuZXR3b3JrX2lkJWOOqAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:tall_grass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRfBAAACAQAbmFtZRQAbWluZWNyYWZ0OnRhbGxfZ3Jhc3MECQBuYW1lX2hhc2ii5MyZJpv4sgMKAG5ldHdvcmtfaWRRfeH4CgYAc3RhdGVzAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:nether_sprouts" + }, + { + "id": "minecraft:fire_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRGAwAACAQAbmFtZRQAbWluZWNyYWZ0OmZpcmVfY29yYWwECQBuYW1lX2hhc2hOHyyECVQVJwMKAG5ldHdvcmtfaWS9vF0UCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:brain_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWREAwAACAQAbmFtZRUAbWluZWNyYWZ0OmJyYWluX2NvcmFsBAkAbmFtZV9oYXNoRiWlLCwA2ycDCgBuZXR3b3JrX2lkrjAuhgoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:bubble_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRFAwAACAQAbmFtZRYAbWluZWNyYWZ0OmJ1YmJsZV9jb3JhbAQJAG5hbWVfaGFzaJz6rWnl+v2qAwoAbmV0d29ya19pZImIWy0KBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:tube_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAQAACAQAbmFtZRQAbWluZWNyYWZ0OnR1YmVfY29yYWwECQBuYW1lX2hhc2iYa8oO/tgk7wMKAG5ldHdvcmtfaWRTfND5CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:horn_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRHAwAACAQAbmFtZRQAbWluZWNyYWZ0Omhvcm5fY29yYWwECQBuYW1lX2hhc2iZnRHjZbnLPgMKAG5ldHdvcmtfaWR+GGp8CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:dead_fire_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRLAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfZmlyZV9jb3JhbAQJAG5hbWVfaGFzaEPU6tFy/latAwoAbmV0d29ya19pZNMa7V4KBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:dead_brain_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRJAwAACAQAbmFtZRoAbWluZWNyYWZ0OmRlYWRfYnJhaW5fY29yYWwECQBuYW1lX2hhc2j5L6QJCISvzwMKAG5ldHdvcmtfaWQkKzeiCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:dead_bubble_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRKAwAACAQAbmFtZRsAbWluZWNyYWZ0OmRlYWRfYnViYmxlX2NvcmFsBAkAbmFtZV9oYXNoSTOZ/8wpeNYDCgBuZXR3b3JrX2lka6w9DAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:dead_tube_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRIAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfdHViZV9jb3JhbAQJAG5hbWVfaGFzaJGjNWhlaIJeAwoAbmV0d29ya19pZO3Z0ygKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:dead_horn_coral", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRMAwAACAQAbmFtZRkAbWluZWNyYWZ0OmRlYWRfaG9ybl9jb3JhbAQJAG5hbWVfaGFzaJBkz3qt+g2cAwoAbmV0d29ya19pZBAN+eYKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:fire_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRJBAAACAQAbmFtZRgAbWluZWNyYWZ0OmZpcmVfY29yYWxfZmFuBAkAbmFtZV9oYXNosOTxYYxsDLgDCgBuZXR3b3JrX2lkFKxbEgoGAHN0YXRlcwMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:brain_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRHBAAACAQAbmFtZRkAbWluZWNyYWZ0OmJyYWluX2NvcmFsX2ZhbgQJAG5hbWVfaGFzaAi5uHizSNcqAwoAbmV0d29ya19pZFtLjNwKBgBzdGF0ZXMDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:bubble_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRIBAAACAQAbmFtZRoAbWluZWNyYWZ0OmJ1YmJsZV9jb3JhbF9mYW4ECQBuYW1lX2hhc2hy/rX2on17DgMKAG5ldHdvcmtfaWQof60VCgYAc3RhdGVzAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:tube_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSEAQAACAQAbmFtZRgAbWluZWNyYWZ0OnR1YmVfY29yYWxfZmFuBAkAbmFtZV9oYXNo9pbJbo+PphIDCgBuZXR3b3JrX2lkenDTYgoGAHN0YXRlcwMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:horn_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRKBAAACAQAbmFtZRgAbWluZWNyYWZ0Omhvcm5fY29yYWxfZmFuBAkAbmFtZV9oYXNoA+ri6NPDkbUDCgBuZXR3b3JrX2lkezoHNwoGAHN0YXRlcwMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:dead_fire_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRNBAAACAQAbmFtZR0AbWluZWNyYWZ0OmRlYWRfZmlyZV9jb3JhbF9mYW4ECQBuYW1lX2hhc2hpQO02NDxPvwMKAG5ldHdvcmtfaWTaOJgLCgYAc3RhdGVzAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:dead_brain_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRLBAAACAQAbmFtZR4AbWluZWNyYWZ0OmRlYWRfYnJhaW5fY29yYWxfZmFuBAkAbmFtZV9oYXNoI9/+Z4YqMhIDCgBuZXR3b3JrX2lkqYXxYgoGAHN0YXRlcwMTAGNvcmFsX2Zhbl9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:dead_bubble_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRMBAAACAQAbmFtZR8AbWluZWNyYWZ0OmRlYWRfYnViYmxlX2NvcmFsX2ZhbgQJAG5hbWVfaGFzaBNECtIM6VIOAwoAbmV0d29ya19pZLrNtBEKBgBzdGF0ZXMDEwBjb3JhbF9mYW5fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:dead_tube_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSFAQAACAQAbmFtZR0AbWluZWNyYWZ0OmRlYWRfdHViZV9jb3JhbF9mYW4ECQBuYW1lX2hhc2hbBBM9jFKWvQMKAG5ldHdvcmtfaWSkJKUWCgYAc3RhdGVzAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:dead_horn_coral_fan", + "block_state_b64": "CgAAAwgAYmxvY2tfaWROBAAACAQAbmFtZR0AbWluZWNyYWZ0OmRlYWRfaG9ybl9jb3JhbF9mYW4ECQBuYW1lX2hhc2hObElFrHfPygMKAG5ldHdvcmtfaWQ1ZxvmCgYAc3RhdGVzAxMAY29yYWxfZmFuX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:crimson_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTeAQAACAQAbmFtZRcAbWluZWNyYWZ0OmNyaW1zb25fcm9vdHMECQBuYW1lX2hhc2j1fWgQLViv5QMKAG5ldHdvcmtfaWRLh5DXCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:warped_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTfAQAACAQAbmFtZRYAbWluZWNyYWZ0OndhcnBlZF9yb290cwQJAG5hbWVfaGFzaBc3WvbJOLlkAwoAbmV0d29ya19pZNLgDnAKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:dandelion", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQlAAAACAQAbmFtZRMAbWluZWNyYWZ0OmRhbmRlbGlvbgQJAG5hbWVfaGFzaBJ3bEUi+Nn/AwoAbmV0d29ya19pZBjjC44KBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:poppy", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAAAACAQAbmFtZQ8AbWluZWNyYWZ0OnBvcHB5BAkAbmFtZV9oYXNocMF8pITMbkcDCgBuZXR3b3JrX2lk8im6ywoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:blue_orchid", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ9BAAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfb3JjaGlkBAkAbmFtZV9oYXNoBjz2MsgB21EDCgBuZXR3b3JrX2lk/iLsSwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:allium", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ+BAAACAQAbmFtZRAAbWluZWNyYWZ0OmFsbGl1bQQJAG5hbWVfaGFzaDCGQBHNDTkcAwoAbmV0d29ya19pZD9Dgr0KBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:azure_bluet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ/BAAACAQAbmFtZRUAbWluZWNyYWZ0OmF6dXJlX2JsdWV0BAkAbmFtZV9oYXNo9N5egqMT2QcDCgBuZXR3b3JrX2lkwIgDnwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:red_tulip", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRABAAACAQAbmFtZRMAbWluZWNyYWZ0OnJlZF90dWxpcAQJAG5hbWVfaGFzaAjMi9Rd+6rhAwoAbmV0d29ya19pZAZCnt8KBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:orange_tulip", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRBBAAACAQAbmFtZRYAbWluZWNyYWZ0Om9yYW5nZV90dWxpcAQJAG5hbWVfaGFzaP+NjxMBZ8vAAwoAbmV0d29ya19pZPYatsMKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:white_tulip", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRCBAAACAQAbmFtZRUAbWluZWNyYWZ0OndoaXRlX3R1bGlwBAkAbmFtZV9oYXNo5vbU4VRPh3ADCgBuZXR3b3JrX2lkok+4rQoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:pink_tulip", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRDBAAACAQAbmFtZRQAbWluZWNyYWZ0OnBpbmtfdHVsaXAECQBuYW1lX2hhc2hxDHZa6OaNXAMKAG5ldHdvcmtfaWTiOT+VCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:oxeye_daisy", + "block_state_b64": "CgAAAwgAYmxvY2tfaWREBAAACAQAbmFtZRUAbWluZWNyYWZ0Om94ZXllX2RhaXN5BAkAbmFtZV9oYXNoXwxsqNQTN9gDCgBuZXR3b3JrX2lkw7R7dwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:cornflower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRFBAAACAQAbmFtZRQAbWluZWNyYWZ0OmNvcm5mbG93ZXIECQBuYW1lX2hhc2gnhyC3EeqHgAMKAG5ldHdvcmtfaWR4VrvACgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:lily_of_the_valley", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRGBAAACAQAbmFtZRwAbWluZWNyYWZ0OmxpbHlfb2ZfdGhlX3ZhbGxleQQJAG5hbWVfaGFzaI64TJSf9mgQAwoAbmV0d29ya19pZFE9+nwKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:sunflower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSvAAAACAQAbmFtZRMAbWluZWNyYWZ0OnN1bmZsb3dlcgQJAG5hbWVfaGFzaAMxYQLoqlZ0AwoAbmV0d29ya19pZA10iSoKBgBzdGF0ZXMBDwB1cHBlcl9ibG9ja19iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:lilac", + "block_state_b64": "CgAAAwgAYmxvY2tfaWReBAAACAQAbmFtZQ8AbWluZWNyYWZ0OmxpbGFjBAkAbmFtZV9oYXNoD3nrQJuo7NkDCgBuZXR3b3JrX2lk5W+uFAoGAHN0YXRlcwEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:rose_bush", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhBAAACAQAbmFtZRMAbWluZWNyYWZ0OnJvc2VfYnVzaAQJAG5hbWVfaGFzaLoiFk8LVpGKAwoAbmV0d29ya19pZMZPv48KBgBzdGF0ZXMBDwB1cHBlcl9ibG9ja19iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:peony", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRiBAAACAQAbmFtZQ8AbWluZWNyYWZ0OnBlb255BAkAbmFtZV9oYXNoR4dYc4QquPADCgBuZXR3b3JrX2lkrTe7RwoGAHN0YXRlcwEPAHVwcGVyX2Jsb2NrX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:pitcher_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAwAACAQAbmFtZRcAbWluZWNyYWZ0OnBpdGNoZXJfcGxhbnQECQBuYW1lX2hhc2hRJHzsbDH+SQMKAG5ldHdvcmtfaWRnY76VCgYAc3RhdGVzAQ8AdXBwZXJfYmxvY2tfYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:pink_petals", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQkAwAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfcGV0YWxzBAkAbmFtZV9oYXNo6DQwN9SwV3QDCgBuZXR3b3JrX2lkNWneGgoGAHN0YXRlcwMGAGdyb3d0aAAAAAAIHABtaW5lY3JhZnQ6Y2FyZGluYWxfZGlyZWN0aW9uBQBzb3V0aAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:wither_rose", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTXAQAACAQAbmFtZRUAbWluZWNyYWZ0OndpdGhlcl9yb3NlBAkAbmFtZV9oYXNoaSKxl3I516gDCgBuZXR3b3JrX2lkATXLPwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:torchflower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ3AwAACAQAbmFtZRUAbWluZWNyYWZ0OnRvcmNoZmxvd2VyBAkAbmFtZV9oYXNoL+mHtElwbqQDCgBuZXR3b3JrX2lkI34O+AoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "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/XeXOLAMKAG5ldHdvcmtfaWSUkDtbCgYAc3RhdGVzAxMAdmluZV9kaXJlY3Rpb25fYml0cwAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:weeping_vines", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTmAQAACAQAbmFtZRcAbWluZWNyYWZ0OndlZXBpbmdfdmluZXMECQBuYW1lX2hhc2jrLgLHkQygiwMKAG5ldHdvcmtfaWQ8NHSJCgYAc3RhdGVzAxEAd2VlcGluZ192aW5lc19hZ2UAAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:twisting_vines", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQeAgAACAQAbmFtZRgAbWluZWNyYWZ0OnR3aXN0aW5nX3ZpbmVzBAkAbmFtZV9oYXNoDYR5QgVUQJADCgBuZXR3b3JrX2lk5kYVIQoGAHN0YXRlcwMSAHR3aXN0aW5nX3ZpbmVzX2FnZQAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:waterlily", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRvAAAACAQAbmFtZRMAbWluZWNyYWZ0OndhdGVybGlseQQJAG5hbWVfaGFzaEHgC4c1SXg0AwoAbmV0d29ya19pZOOerp8KBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:seagrass", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSBAQAACAQAbmFtZRIAbWluZWNyYWZ0OnNlYWdyYXNzBAkAbmFtZV9oYXNoHSBFtoHdWxIDCgBuZXR3b3JrX2lkd3lhEAoGAHN0YXRlcwgOAHNlYV9ncmFzc190eXBlBwBkZWZhdWx0AAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:kelp" + }, + { + "id": "minecraft:deadbush", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQgAAAACAQAbmFtZRIAbWluZWNyYWZ0OmRlYWRidXNoBAkAbmFtZV9oYXNoPFODe4IScnYDCgBuZXR3b3JrX2lkVfnl+goGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:bamboo", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAQAACAQAbmFtZRAAbWluZWNyYWZ0OmJhbWJvbwQJAG5hbWVfaGFzaBgpGmyzhedCAwoAbmV0d29ya19pZIZv1nYKBgBzdGF0ZXMBBwBhZ2VfYml0AAgQAGJhbWJvb19sZWFmX3NpemUJAG5vX2xlYXZlcwgWAGJhbWJvb19zdGFsa190aGlja25lc3MEAHRoaW4AAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:snow", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRQAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnNub3cECQBuYW1lX2hhc2gVHr5XXdETWAMKAG5ldHdvcmtfaWQ0zCeHCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:ice", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRPAAAACAQAbmFtZQ0AbWluZWNyYWZ0OmljZQQJAG5hbWVfaGFzaNF26f+uUT29AwoAbmV0d29ya19pZOUMaQYKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:packed_ice", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSuAAAACAQAbmFtZRQAbWluZWNyYWZ0OnBhY2tlZF9pY2UECQBuYW1lX2hhc2hk4bu123ZrFgMKAG5ldHdvcmtfaWTr/ooaCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:blue_ice", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQKAQAACAQAbmFtZRIAbWluZWNyYWZ0OmJsdWVfaWNlBAkAbmFtZV9oYXNo+EKxYgFhKcgDCgBuZXR3b3JrX2lkxfsA8goGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:snow_layer", + "block_state_b64": "CgAAAwgAYmxvY2tfaWROAAAACAQAbmFtZRQAbWluZWNyYWZ0OnNub3dfbGF5ZXIECQBuYW1lX2hhc2hXka6atMYUCQMKAG5ldHdvcmtfaWRCrIPcCgYAc3RhdGVzAQsAY292ZXJlZF9iaXQAAwYAaGVpZ2h0AAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:pointed_dripstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQzAgAACAQAbmFtZRsAbWluZWNyYWZ0OnBvaW50ZWRfZHJpcHN0b25lBAkAbmFtZV9oYXNoJMISzmHQgt8DCgBuZXR3b3JrX2lkbWrtYgoGAHN0YXRlcwgTAGRyaXBzdG9uZV90aGlja25lc3MDAHRpcAEHAGhhbmdpbmcBAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:dripstone_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ8AgAACAQAbmFtZRkAbWluZWNyYWZ0OmRyaXBzdG9uZV9ibG9jawQJAG5hbWVfaGFzaIIXnEqY77YsAwoAbmV0d29ya19pZMZi2kwKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:moss_carpet", + "block_state_b64": "CgAAAwgAYmxvY2tfaWROAgAACAQAbmFtZRUAbWluZWNyYWZ0Om1vc3NfY2FycGV0BAkAbmFtZV9oYXNo/NEDxRPTshYDCgBuZXR3b3JrX2lkaGG3QwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:moss_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ/AgAACAQAbmFtZRQAbWluZWNyYWZ0Om1vc3NfYmxvY2sECQBuYW1lX2hhc2iovcsPUYX2tgMKAG5ldHdvcmtfaWT3JSbfCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:dirt_with_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ9AgAACAQAbmFtZRkAbWluZWNyYWZ0OmRpcnRfd2l0aF9yb290cwQJAG5hbWVfaGFzaLCNDYPviDCIAwoAbmV0d29ya19pZNCkwzoKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:hanging_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ+AgAACAQAbmFtZRcAbWluZWNyYWZ0Omhhbmdpbmdfcm9vdHMECQBuYW1lX2hhc2jaXn+Y5UZpDAMKAG5ldHdvcmtfaWRU4c2vCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:mangrove_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWThAgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hbmdyb3ZlX3Jvb3RzBAkAbmFtZV9oYXNoa786PzQGZ6kDCgBuZXR3b3JrX2lklA0AHgoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:muddy_mangrove_roots", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTiAgAACAQAbmFtZR4AbWluZWNyYWZ0Om11ZGR5X21hbmdyb3ZlX3Jvb3RzBAkAbmFtZV9oYXNo9YApdHpo1RkDCgBuZXR3b3JrX2lkH0Oc4woGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:big_dripleaf", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRCAgAACAQAbmFtZRYAbWluZWNyYWZ0OmJpZ19kcmlwbGVhZgQJAG5hbWVfaGFzaGBEhXjo6qSdAwoAbmV0d29ya19pZMETsb8KBgBzdGF0ZXMBEQBiaWdfZHJpcGxlYWZfaGVhZAEIEQBiaWdfZHJpcGxlYWZfdGlsdAQAbm9uZQgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:small_dripleaf_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRPAgAACAQAbmFtZR4AbWluZWNyYWZ0OnNtYWxsX2RyaXBsZWFmX2Jsb2NrBAkAbmFtZV9oYXNojxRAgXP9uWADCgBuZXR3b3JrX2lkozbVPwoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24EAGVhc3QBDwB1cHBlcl9ibG9ja19iaXQBAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:spore_blossom", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRAAgAACAQAbmFtZRcAbWluZWNyYWZ0OnNwb3JlX2Jsb3Nzb20ECQBuYW1lX2hhc2il3U72Gbco2gMKAG5ldHdvcmtfaWSbbbgcCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:azalea", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRQAgAACAQAbmFtZRAAbWluZWNyYWZ0OmF6YWxlYQQJAG5hbWVfaGFzaNyUl+BW9JrBAwoAbmV0d29ya19pZO/XZtQKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:flowering_azalea", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRRAgAACAQAbmFtZRoAbWluZWNyYWZ0OmZsb3dlcmluZ19hemFsZWEECQBuYW1lX2hhc2ie9r33wz8kiwMKAG5ldHdvcmtfaWQ3ij0VCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:glow_lichen", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSaAgAACAQAbmFtZRUAbWluZWNyYWZ0Omdsb3dfbGljaGVuBAkAbmFtZV9oYXNobyPUrIYlo44DCgBuZXR3b3JrX2lkCh8lSAoGAHN0YXRlcwMZAG11bHRpX2ZhY2VfZGlyZWN0aW9uX2JpdHM/AAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:amethyst_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRGAgAACAQAbmFtZRgAbWluZWNyYWZ0OmFtZXRoeXN0X2Jsb2NrBAkAbmFtZV9oYXNob+JK1iiAthcDCgBuZXR3b3JrX2lk8HtpzgoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:budding_amethyst", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRHAgAACAQAbmFtZRoAbWluZWNyYWZ0OmJ1ZGRpbmdfYW1ldGh5c3QECQBuYW1lX2hhc2gJvAwfI14fxgMKAG5ldHdvcmtfaWTQYqfACgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:amethyst_cluster", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRIAgAACAQAbmFtZRoAbWluZWNyYWZ0OmFtZXRoeXN0X2NsdXN0ZXIECQBuYW1lX2hhc2jK82S88Jgm8wMKAG5ldHdvcmtfaWSCPMPGCgYAc3RhdGVzCBQAbWluZWNyYWZ0OmJsb2NrX2ZhY2UCAHVwAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:large_amethyst_bud", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRJAgAACAQAbmFtZRwAbWluZWNyYWZ0OmxhcmdlX2FtZXRoeXN0X2J1ZAQJAG5hbWVfaGFzaAHhdpWD+sd5AwoAbmV0d29ya19pZKkQxOcKBgBzdGF0ZXMIFABtaW5lY3JhZnQ6YmxvY2tfZmFjZQIAdXAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:medium_amethyst_bud", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRKAgAACAQAbmFtZR0AbWluZWNyYWZ0Om1lZGl1bV9hbWV0aHlzdF9idWQECQBuYW1lX2hhc2g5lBGtC0DzZQMKAG5ldHdvcmtfaWSYiP4gCgYAc3RhdGVzCBQAbWluZWNyYWZ0OmJsb2NrX2ZhY2UCAHVwAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:small_amethyst_bud", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRLAgAACAQAbmFtZRwAbWluZWNyYWZ0OnNtYWxsX2FtZXRoeXN0X2J1ZAQJAG5hbWVfaGFzaEnb4+q9PO4YAwoAbmV0d29ya19pZGWzxrQKBgBzdGF0ZXMIFABtaW5lY3JhZnQ6YmxvY2tfZmFjZQIAdXAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:tuff", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRMAgAACAQAbmFtZQ4AbWluZWNyYWZ0OnR1ZmYECQBuYW1lX2hhc2h1Rwc1XYsBGwMKAG5ldHdvcmtfaWRwQGn0CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:tuff_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTpAwAACAQAbmFtZRUAbWluZWNyYWZ0OnR1ZmZfc3RhaXJzBAkAbmFtZV9oYXNoKjyNUBjcfZsDCgBuZXR3b3JrX2lk+LsycgoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:tuff_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTnAwAACAQAbmFtZRMAbWluZWNyYWZ0OnR1ZmZfc2xhYgQJAG5hbWVfaGFzaIhCGdlIsnMUAwoAbmV0d29ya19pZN1dUL4KBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:tuff_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTqAwAACAQAbmFtZRMAbWluZWNyYWZ0OnR1ZmZfd2FsbAQJAG5hbWVfaGFzaMyeeu1IRf03AwoAbmV0d29ya19pZDkIrosKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:chiseled_tuff", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTwAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoaXNlbGVkX3R1ZmYECQBuYW1lX2hhc2iVliOT8OTQ9AMKAG5ldHdvcmtfaWTLNKOiCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:polished_tuff", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTrAwAACAQAbmFtZRcAbWluZWNyYWZ0OnBvbGlzaGVkX3R1ZmYECQBuYW1lX2hhc2hyaLe/KEVZ0gMKAG5ldHdvcmtfaWTcX3NrCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:polished_tuff_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTuAwAACAQAbmFtZR4AbWluZWNyYWZ0OnBvbGlzaGVkX3R1ZmZfc3RhaXJzBAkAbmFtZV9oYXNo8yuah8QI1dcDCgBuZXR3b3JrX2lkjLoU4AoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:polished_tuff_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTsAwAACAQAbmFtZRwAbWluZWNyYWZ0OnBvbGlzaGVkX3R1ZmZfc2xhYgQJAG5hbWVfaGFzaLXdb48YvAsHAwoAbmV0d29ya19pZAnJ7W0KBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:polished_tuff_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTvAwAACAQAbmFtZRwAbWluZWNyYWZ0OnBvbGlzaGVkX3R1ZmZfd2FsbAQJAG5hbWVfaGFzaJVZj6QYWXUrAwoAbmV0d29ya19pZLU7dooKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:tuff_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTxAwAACAQAbmFtZRUAbWluZWNyYWZ0OnR1ZmZfYnJpY2tzBAkAbmFtZV9oYXNo/hbQ+mXSK7wDCgBuZXR3b3JrX2lk6gmIwQoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:tuff_brick_stairs", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT0AwAACAQAbmFtZRsAbWluZWNyYWZ0OnR1ZmZfYnJpY2tfc3RhaXJzBAkAbmFtZV9oYXNoWJpkAurUfKwDCgBuZXR3b3JrX2lkUMcjiwoGAHN0YXRlcwEPAHVwc2lkZV9kb3duX2JpdAADEAB3ZWlyZG9fZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:tuff_brick_slab", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTyAwAACAQAbmFtZRkAbWluZWNyYWZ0OnR1ZmZfYnJpY2tfc2xhYgQJAG5hbWVfaGFzaLqPMjVCv5dIAwoAbmV0d29ya19pZOmeRhcKBgBzdGF0ZXMIFwBtaW5lY3JhZnQ6dmVydGljYWxfaGFsZgYAYm90dG9tAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:tuff_brick_wall", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT1AwAACAQAbmFtZRkAbWluZWNyYWZ0OnR1ZmZfYnJpY2tfd2FsbAQJAG5hbWVfaGFzaIL0IyNCOsonAwoAbmV0d29ya19pZJW4T5UKBgBzdGF0ZXMIGQB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9lYXN0BABub25lCBoAd2FsbF9jb25uZWN0aW9uX3R5cGVfbm9ydGgEAG5vbmUIGgB3YWxsX2Nvbm5lY3Rpb25fdHlwZV9zb3V0aAQAbm9uZQgZAHdhbGxfY29ubmVjdGlvbl90eXBlX3dlc3QEAG5vbmUBDQB3YWxsX3Bvc3RfYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:chiseled_tuff_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT2AwAACAQAbmFtZR4AbWluZWNyYWZ0OmNoaXNlbGVkX3R1ZmZfYnJpY2tzBAkAbmFtZV9oYXNo3oQw6gmxYuADCgBuZXR3b3JrX2lkm3D8AgoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:calcite", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRFAgAACAQAbmFtZREAbWluZWNyYWZ0OmNhbGNpdGUECQBuYW1lX2hhc2ixKLu8ZIdzDQMKAG5ldHdvcmtfaWQlSbJDCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "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/FO78WDoDCgBuZXR3b3JrX2lkLh1OXAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:red_mushroom", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQoAAAACAQAbmFtZRYAbWluZWNyYWZ0OnJlZF9tdXNocm9vbQQJAG5hbWVfaGFzaPpzJua7669xAwoAbmV0d29ya19pZCvWPYkKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:crimson_fungus", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTjAQAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fZnVuZ3VzBAkAbmFtZV9oYXNolIcCUuFM2u0DCgBuZXR3b3JrX2lkD2NN0QoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:warped_fungus", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTkAQAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9mdW5ndXMECQBuYW1lX2hhc2gq8bSnRVTAFgMKAG5ldHdvcmtfaWTkwS+rCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:brown_mushroom_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAAAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkdOMhDAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cw4AAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:red_mushroom_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRkAAAACAQAbmFtZRwAbWluZWNyYWZ0OnJlZF9tdXNocm9vbV9ibG9jawQJAG5hbWVfaGFzaJTTyJbth9M9AwoAbmV0d29ya19pZM+AyboKBgBzdGF0ZXMDEgBodWdlX211c2hyb29tX2JpdHMOAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:brown_mushroom_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAAAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkbdt3CAoGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cw8AAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:brown_mushroom_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRjAAAACAQAbmFtZR4AbWluZWNyYWZ0OmJyb3duX211c2hyb29tX2Jsb2NrBAkAbmFtZV9oYXNoIyjnbI6xy9sDCgBuZXR3b3JrX2lkSrMl9goGAHN0YXRlcwMSAGh1Z2VfbXVzaHJvb21fYml0cwAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:egg" + }, + { + "id": "minecraft:sugar_cane" + }, + { + "id": "minecraft:sugar" + }, + { + "id": "minecraft:rotten_flesh" + }, + { + "id": "minecraft:bone" + }, + { + "id": "minecraft:web", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQeAAAACAQAbmFtZQ0AbWluZWNyYWZ0OndlYgQJAG5hbWVfaGFzaA4GKQCvG4i9AwoAbmV0d29ya19pZApt+jgKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:spider_eye" + }, + { + "id": "minecraft:mob_spawner", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ0AAAACAQAbmFtZRUAbWluZWNyYWZ0Om1vYl9zcGF3bmVyBAkAbmFtZV9oYXNoNwGrCV/Fkh8DCgBuZXR3b3JrX2lkM1wTmgoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:trial_spawner", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ6AgAACAQAbmFtZRcAbWluZWNyYWZ0OnRyaWFsX3NwYXduZXIECQBuYW1lX2hhc2iNLRPB4ACz+QMKAG5ldHdvcmtfaWTWFYHGCgYAc3RhdGVzAQcAb21pbm91cwADEwB0cmlhbF9zcGF3bmVyX3N0YXRlAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:vault", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ5AgAACAQAbmFtZQ8AbWluZWNyYWZ0OnZhdWx0BAkAbmFtZV9oYXNoCAp9n3IAyqcDCgBuZXR3b3JrX2lk6/P+vwoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAQcAb21pbm91cwAICwB2YXVsdF9zdGF0ZQgAaW5hY3RpdmUAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:end_portal_frame", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR4AAAACAQAbmFtZRoAbWluZWNyYWZ0OmVuZF9wb3J0YWxfZnJhbWUECQBuYW1lX2hhc2gqofyUIjGOpQMKAG5ldHdvcmtfaWRbGHf8CgYAc3RhdGVzARIAZW5kX3BvcnRhbF9leWVfYml0AAgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:infested_stone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRhAAAACAQAbmFtZRgAbWluZWNyYWZ0OmluZmVzdGVkX3N0b25lBAkAbmFtZV9oYXNoxnRcHDu4zqQDCgBuZXR3b3JrX2lkpfcnsgoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:infested_cobblestone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRZBAAACAQAbmFtZR4AbWluZWNyYWZ0OmluZmVzdGVkX2NvYmJsZXN0b25lBAkAbmFtZV9oYXNoy+LVCKG2kVMDCgBuZXR3b3JrX2lkpn+icAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:infested_stone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRaBAAACAQAbmFtZR8AbWluZWNyYWZ0OmluZmVzdGVkX3N0b25lX2JyaWNrcwQJAG5hbWVfaGFzaBMnals7a32CAwoAbmV0d29ya19pZNHi2UYKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:infested_mossy_stone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRbBAAACAQAbmFtZSUAbWluZWNyYWZ0OmluZmVzdGVkX21vc3N5X3N0b25lX2JyaWNrcwQJAG5hbWVfaGFzaAmJk+HmVq0rAwoAbmV0d29ya19pZAVH8/sKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:infested_cracked_stone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRcBAAACAQAbmFtZScAbWluZWNyYWZ0OmluZmVzdGVkX2NyYWNrZWRfc3RvbmVfYnJpY2tzBAkAbmFtZV9oYXNoMyc60XcfcyoDCgBuZXR3b3JrX2lkaW+kbQoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:infested_chiseled_stone_bricks", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRdBAAACAQAbmFtZSgAbWluZWNyYWZ0OmluZmVzdGVkX2NoaXNlbGVkX3N0b25lX2JyaWNrcwQJAG5hbWVfaGFzaNUvNIIg9dZbAwoAbmV0d29ya19pZCajGicKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:infested_deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTFAgAACAQAbmFtZRwAbWluZWNyYWZ0OmluZmVzdGVkX2RlZXBzbGF0ZQQJAG5hbWVfaGFzaICF2VYccxF1AwoAbmV0d29ya19pZDa/624KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:dragon_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR6AAAACAQAbmFtZRQAbWluZWNyYWZ0OmRyYWdvbl9lZ2cECQBuYW1lX2hhc2inMzXrV+/e1wMKAG5ldHdvcmtfaWTgO1yRCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:turtle_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAQAACAQAbmFtZRQAbWluZWNyYWZ0OnR1cnRsZV9lZ2cECQBuYW1lX2hhc2iwSRcxOJIJ9gMKAG5ldHdvcmtfaWSIRNUhCgYAc3RhdGVzCA0AY3JhY2tlZF9zdGF0ZQkAbm9fY3JhY2tzCBAAdHVydGxlX2VnZ19jb3VudAcAb25lX2VnZwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:sniffer_egg", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRTAwAACAQAbmFtZRUAbWluZWNyYWZ0OnNuaWZmZXJfZWdnBAkAbmFtZV9oYXNoY1lozc8lPcYDCgBuZXR3b3JrX2lk7yb/2QoGAHN0YXRlcwgNAGNyYWNrZWRfc3RhdGUJAG5vX2NyYWNrcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:frog_spawn", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTTAgAACAQAbmFtZRQAbWluZWNyYWZ0OmZyb2dfc3Bhd24ECQBuYW1lX2hhc2iWmd7idp3ZZwMKAG5ldHdvcmtfaWRFzJudCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:pearlescent_froglight", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTUAgAACAQAbmFtZR8AbWluZWNyYWZ0OnBlYXJsZXNjZW50X2Zyb2dsaWdodAQJAG5hbWVfaGFzaKkcFRyycYGyAwoAbmV0d29ya19pZJqYakAKBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:verdant_froglight", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTVAgAACAQAbmFtZRsAbWluZWNyYWZ0OnZlcmRhbnRfZnJvZ2xpZ2h0BAkAbmFtZV9oYXNoA+eXuTBohrQDCgBuZXR3b3JrX2lkDIVnsQoGAHN0YXRlcwgLAHBpbGxhcl9heGlzAQB5AAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:ochre_froglight", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTWAgAACAQAbmFtZRkAbWluZWNyYWZ0Om9jaHJlX2Zyb2dsaWdodAQJAG5hbWVfaGFzaMY59kjPe+c3AwoAbmV0d29ya19pZO2TD50KBgBzdGF0ZXMICwBwaWxsYXJfYXhpcwEAeQADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "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:breeze_spawn_egg" + }, + { + "id": "minecraft:armadillo_spawn_egg" + }, + { + "id": "minecraft:bogged_spawn_egg" + }, + { + "id": "minecraft:obsidian", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQxAAAACAQAbmFtZRIAbWluZWNyYWZ0Om9ic2lkaWFuBAkAbmFtZV9oYXNoiz4qrb8QjyEDCgBuZXR3b3JrX2lkuqnPpQoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:crying_obsidian", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQgAgAACAQAbmFtZRkAbWluZWNyYWZ0OmNyeWluZ19vYnNpZGlhbgQJAG5hbWVfaGFzaKT0JlA7Z1K+AwoAbmV0d29ya19pZCjbPV4KBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:bedrock", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQHAAAACAQAbmFtZREAbWluZWNyYWZ0OmJlZHJvY2sECQBuYW1lX2hhc2hWfFrh4LVtxwMKAG5ldHdvcmtfaWT7fKz1CgYAc3RhdGVzAQ4AaW5maW5pYnVybl9iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:soul_sand", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRYAAAACAQAbmFtZRMAbWluZWNyYWZ0OnNvdWxfc2FuZAQJAG5hbWVfaGFzaMaf+bccu+KTAwoAbmV0d29ya19pZBQSHrMKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:magma", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTVAAAACAQAbmFtZQ8AbWluZWNyYWZ0Om1hZ21hBAkAbmFtZV9oYXNoqyTjKaIsWfYDCgBuZXR3b3JrX2lkyfWAZgoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:nether_wart" + }, + { + "id": "minecraft:end_stone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR5AAAACAQAbmFtZRMAbWluZWNyYWZ0OmVuZF9zdG9uZQQJAG5hbWVfaGFzaH1J9jA39GJNAwoAbmV0d29ya19pZFeFQ7UKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:chorus_flower", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTIAAAACAQAbmFtZRcAbWluZWNyYWZ0OmNob3J1c19mbG93ZXIECQBuYW1lX2hhc2iMpSodli5uawMKAG5ldHdvcmtfaWRnd1ZWCgYAc3RhdGVzAwMAYWdlAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:chorus_plant", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTwAAAACAQAbmFtZRYAbWluZWNyYWZ0OmNob3J1c19wbGFudAQJAG5hbWVfaGFzaJhSrmNGKwaMAwoAbmV0d29ya19pZA3uVqMKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:chorus_fruit" + }, + { + "id": "minecraft:popped_chorus_fruit" + }, + { + "id": "minecraft:sponge", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQTAAAACAQAbmFtZRAAbWluZWNyYWZ0OnNwb25nZQQJAG5hbWVfaGFzaLrd2ScYRDMiAwoAbmV0d29ya19pZNmQW/oKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:wet_sponge", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTXBAAACAQAbmFtZRQAbWluZWNyYWZ0OndldF9zcG9uZ2UECQBuYW1lX2hhc2htp6nKpSHcAgMKAG5ldHdvcmtfaWQaW+fCCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:tube_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAQAACAQAbmFtZRoAbWluZWNyYWZ0OnR1YmVfY29yYWxfYmxvY2sECQBuYW1lX2hhc2iGkaiR7Eot4wMKAG5ldHdvcmtfaWQPNJ6sCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:brain_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRQBAAACAQAbmFtZRsAbWluZWNyYWZ0OmJyYWluX2NvcmFsX2Jsb2NrBAkAbmFtZV9oYXNoeDNAK18yUo4DCgBuZXR3b3JrX2lkloN1vgoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:bubble_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRRBAAACAQAbmFtZRwAbWluZWNyYWZ0OmJ1YmJsZV9jb3JhbF9ibG9jawQJAG5hbWVfaGFzaAI2mwMlvcNbAwoAbmV0d29ya19pZBlkxKIKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:fire_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRSBAAACAQAbmFtZRoAbWluZWNyYWZ0OmZpcmVfY29yYWxfYmxvY2sECQBuYW1lX2hhc2gg1gLeXLmKaAMKAG5ldHdvcmtfaWSp3W57CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:horn_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRTBAAACAQAbmFtZRoAbWluZWNyYWZ0Omhvcm5fY29yYWxfYmxvY2sECQBuYW1lX2hhc2hnZSLRWUwGhAMKAG5ldHdvcmtfaWRSK6ccCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:dead_tube_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRUBAAACAQAbmFtZR8AbWluZWNyYWZ0OmRlYWRfdHViZV9jb3JhbF9ibG9jawQJAG5hbWVfaGFzaB9+lY3hAkNNAwoAbmV0d29ya19pZF0hKKYKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:dead_brain_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRVBAAACAQAbmFtZSAAbWluZWNyYWZ0OmRlYWRfYnJhaW5fY29yYWxfYmxvY2sECQBuYW1lX2hhc2iHyDn52AO8uwMKAG5ldHdvcmtfaWQw7yCaCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:dead_bubble_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRWBAAACAQAbmFtZSEAbWluZWNyYWZ0OmRlYWRfYnViYmxlX2NvcmFsX2Jsb2NrBAkAbmFtZV9oYXNotwkk/ITrsjADCgBuZXR3b3JrX2lk56mXUgoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:dead_fire_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRXBAAACAQAbmFtZR8AbWluZWNyYWZ0OmRlYWRfZmlyZV9jb3JhbF9ibG9jawQJAG5hbWVfaGFzaG0qHxbIrBEyAwoAbmV0d29ya19pZFvnH88KBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:dead_horn_coral_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRYBAAACAQAbmFtZR8AbWluZWNyYWZ0OmRlYWRfaG9ybl9jb3JhbF9ibG9jawQJAG5hbWVfaGFzaL7D8bu4Fm+0AwoAbmV0d29ya19pZEALRLoKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:sculk", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAgAACAQAbmFtZQ8AbWluZWNyYWZ0OnNjdWxrBAkAbmFtZV9oYXNo2Lq7T5yQF8kDCgBuZXR3b3JrX2lkyqUPPgoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:sculk_vein", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTKAgAACAQAbmFtZRQAbWluZWNyYWZ0OnNjdWxrX3ZlaW4ECQBuYW1lX2hhc2gJUdhVooV4zwMKAG5ldHdvcmtfaWSUfn1XCgYAc3RhdGVzAxkAbXVsdGlfZmFjZV9kaXJlY3Rpb25fYml0cwAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:sculk_catalyst", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAgAACAQAbmFtZRgAbWluZWNyYWZ0OnNjdWxrX2NhdGFseXN0BAkAbmFtZV9oYXNo+gCpbrCHST4DCgBuZXR3b3JrX2lkMJ2n/woGAHN0YXRlcwEFAGJsb29tAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:sculk_shrieker", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTMAgAACAQAbmFtZRgAbWluZWNyYWZ0OnNjdWxrX3Nocmlla2VyBAkAbmFtZV9oYXNo5OXtyObniQ4DCgBuZXR3b3JrX2lkxapoNAoGAHN0YXRlcwEGAGFjdGl2ZQABCgBjYW5fc3VtbW9uAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:sculk_sensor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQyAgAACAQAbmFtZRYAbWluZWNyYWZ0OnNjdWxrX3NlbnNvcgQJAG5hbWVfaGFzaCkmHreeTgNnAwoAbmV0d29ya19pZLj2WPcKBgBzdGF0ZXMDEgBzY3Vsa19zZW5zb3JfcGhhc2UAAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:calibrated_sculk_sensor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRDAwAACAQAbmFtZSEAbWluZWNyYWZ0OmNhbGlicmF0ZWRfc2N1bGtfc2Vuc29yBAkAbmFtZV9oYXNoffAcXXN/iJUDCgBuZXR3b3JrX2lkwOx3QQoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAxIAc2N1bGtfc2Vuc29yX3BoYXNlAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:reinforced_deepslate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTRAgAACAQAbmFtZR4AbWluZWNyYWZ0OnJlaW5mb3JjZWRfZGVlcHNsYXRlBAkAbmFtZV9oYXNoldDmj91EapQDCgBuZXR3b3JrX2lkHIt+aQoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "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:mace" + }, + { + "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: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" + }, + { + "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:wind_charge" + }, + { + "id": "minecraft:shears" + }, + { + "id": "minecraft:flint_and_steel" + }, + { + "id": "minecraft:lead" + }, + { + "id": "minecraft:clock" + }, + { + "id": "minecraft:compass" + }, + { + "id": "minecraft:recovery_compass" + }, + { + "id": "minecraft:goat_horn" + }, + { + "id": "minecraft:goat_horn", + "damage": 1 + }, + { + "id": "minecraft:goat_horn", + "damage": 2 + }, + { + "id": "minecraft:goat_horn", + "damage": 3 + }, + { + "id": "minecraft:goat_horn", + "damage": 4 + }, + { + "id": "minecraft:goat_horn", + "damage": 5 + }, + { + "id": "minecraft:goat_horn", + "damage": 6 + }, + { + "id": "minecraft:goat_horn", + "damage": 7 + }, + { + "id": "minecraft:empty_map" + }, + { + "id": "minecraft:empty_map", + "damage": 2 + }, + { + "id": "minecraft:saddle" + }, + { + "id": "minecraft:leather_horse_armor" + }, + { + "id": "minecraft:iron_horse_armor" + }, + { + "id": "minecraft:golden_horse_armor" + }, + { + "id": "minecraft:diamond_horse_armor" + }, + { + "id": "minecraft:wolf_armor" + }, + { + "id": "minecraft:trident" + }, + { + "id": "minecraft:turtle_helmet" + }, + { + "id": "minecraft:elytra" + }, + { + "id": "minecraft:totem_of_undying" + }, + { + "id": "minecraft:glass_bottle" + }, + { + "id": "minecraft:experience_bottle" + }, + { + "id": "minecraft:potion" + }, + { + "id": "minecraft:potion", + "damage": 1 + }, + { + "id": "minecraft:potion", + "damage": 2 + }, + { + "id": "minecraft:potion", + "damage": 3 + }, + { + "id": "minecraft:potion", + "damage": 4 + }, + { + "id": "minecraft:potion", + "damage": 5 + }, + { + "id": "minecraft:potion", + "damage": 6 + }, + { + "id": "minecraft:potion", + "damage": 7 + }, + { + "id": "minecraft:potion", + "damage": 8 + }, + { + "id": "minecraft:potion", + "damage": 9 + }, + { + "id": "minecraft:potion", + "damage": 10 + }, + { + "id": "minecraft:potion", + "damage": 11 + }, + { + "id": "minecraft:potion", + "damage": 12 + }, + { + "id": "minecraft:potion", + "damage": 13 + }, + { + "id": "minecraft:potion", + "damage": 14 + }, + { + "id": "minecraft:potion", + "damage": 15 + }, + { + "id": "minecraft:potion", + "damage": 16 + }, + { + "id": "minecraft:potion", + "damage": 17 + }, + { + "id": "minecraft:potion", + "damage": 18 + }, + { + "id": "minecraft:potion", + "damage": 19 + }, + { + "id": "minecraft:potion", + "damage": 20 + }, + { + "id": "minecraft:potion", + "damage": 21 + }, + { + "id": "minecraft:potion", + "damage": 22 + }, + { + "id": "minecraft:potion", + "damage": 23 + }, + { + "id": "minecraft:potion", + "damage": 24 + }, + { + "id": "minecraft:potion", + "damage": 25 + }, + { + "id": "minecraft:potion", + "damage": 26 + }, + { + "id": "minecraft:potion", + "damage": 27 + }, + { + "id": "minecraft:potion", + "damage": 28 + }, + { + "id": "minecraft:potion", + "damage": 29 + }, + { + "id": "minecraft:potion", + "damage": 30 + }, + { + "id": "minecraft:potion", + "damage": 31 + }, + { + "id": "minecraft:potion", + "damage": 32 + }, + { + "id": "minecraft:potion", + "damage": 33 + }, + { + "id": "minecraft:potion", + "damage": 34 + }, + { + "id": "minecraft:potion", + "damage": 35 + }, + { + "id": "minecraft:potion", + "damage": 36 + }, + { + "id": "minecraft:potion", + "damage": 37 + }, + { + "id": "minecraft:potion", + "damage": 38 + }, + { + "id": "minecraft:potion", + "damage": 39 + }, + { + "id": "minecraft:potion", + "damage": 40 + }, + { + "id": "minecraft:potion", + "damage": 41 + }, + { + "id": "minecraft:potion", + "damage": 42 + }, + { + "id": "minecraft:potion", + "damage": 43 + }, + { + "id": "minecraft:potion", + "damage": 44 + }, + { + "id": "minecraft:potion", + "damage": 45 + }, + { + "id": "minecraft:potion", + "damage": 46 + }, + { + "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: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" + }, + { + "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: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" + }, + { + "id": "minecraft:brush" + }, + { + "id": "minecraft:stick" + }, + { + "id": "minecraft:bed" + }, + { + "id": "minecraft:bed", + "damage": 8 + }, + { + "id": "minecraft:bed", + "damage": 7 + }, + { + "id": "minecraft:bed", + "damage": 15 + }, + { + "id": "minecraft:bed", + "damage": 12 + }, + { + "id": "minecraft:bed", + "damage": 14 + }, + { + "id": "minecraft:bed", + "damage": 1 + }, + { + "id": "minecraft:bed", + "damage": 4 + }, + { + "id": "minecraft:bed", + "damage": 5 + }, + { + "id": "minecraft:bed", + "damage": 13 + }, + { + "id": "minecraft:bed", + "damage": 9 + }, + { + "id": "minecraft:bed", + "damage": 3 + }, + { + "id": "minecraft:bed", + "damage": 11 + }, + { + "id": "minecraft:bed", + "damage": 10 + }, + { + "id": "minecraft:bed", + "damage": 2 + }, + { + "id": "minecraft:bed", + "damage": 6 + }, + { + "id": "minecraft:torch", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQyAAAACAQAbmFtZQ8AbWluZWNyYWZ0OnRvcmNoBAkAbmFtZV9oYXNoagn7rmDBzisDCgBuZXR3b3JrX2lk+BwwuQoGAHN0YXRlcwgWAHRvcmNoX2ZhY2luZ19kaXJlY3Rpb24HAHVua25vd24AAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:soul_torch", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQLAgAACAQAbmFtZRQAbWluZWNyYWZ0OnNvdWxfdG9yY2gECQBuYW1lX2hhc2huixOT04BRdQMKAG5ldHdvcmtfaWShbFILCgYAc3RhdGVzCBYAdG9yY2hfZmFjaW5nX2RpcmVjdGlvbgcAdW5rbm93bgADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:sea_pickle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAQAACAQAbmFtZRQAbWluZWNyYWZ0OnNlYV9waWNrbGUECQBuYW1lX2hhc2iONEfZJB+glgMKAG5ldHdvcmtfaWSINWQyCgYAc3RhdGVzAw0AY2x1c3Rlcl9jb3VudAAAAAABCABkZWFkX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:lantern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTPAQAACAQAbmFtZREAbWluZWNyYWZ0OmxhbnRlcm4ECQBuYW1lX2hhc2hMw44VI2HWygMKAG5ldHdvcmtfaWRkjQvzCgYAc3RhdGVzAQcAaGFuZ2luZwAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:soul_lantern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQMAgAACAQAbmFtZRYAbWluZWNyYWZ0OnNvdWxfbGFudGVybgQJAG5hbWVfaGFzaGjIpjxk9z+RAwoAbmV0d29ya19pZGfoP8cKBgBzdGF0ZXMBBwBoYW5naW5nAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSbAgAACAQAbmFtZRAAbWluZWNyYWZ0OmNhbmRsZQQJAG5hbWVfaGFzaHPd+MsNdWTfAwoAbmV0d29ya19pZHsBMA0KBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:white_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWScAgAACAQAbmFtZRYAbWluZWNyYWZ0OndoaXRlX2NhbmRsZQQJAG5hbWVfaGFzaN1EG5Q1mHiEAwoAbmV0d29ya19pZKN1mmgKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:orange_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSdAgAACAQAbmFtZRcAbWluZWNyYWZ0Om9yYW5nZV9jYW5kbGUECQBuYW1lX2hhc2jySEVWHgUIHQMKAG5ldHdvcmtfaWSfVz82CgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:magenta_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSeAgAACAQAbmFtZRgAbWluZWNyYWZ0Om1hZ2VudGFfY2FuZGxlBAkAbmFtZV9oYXNoG0u6YIOoBSEDCgBuZXR3b3JrX2lk9xGNkQoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:light_blue_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSfAgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfY2FuZGxlBAkAbmFtZV9oYXNocXGeK0zgrG0DCgBuZXR3b3JrX2lk2m1y8goGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:yellow_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSgAgAACAQAbmFtZRcAbWluZWNyYWZ0OnllbGxvd19jYW5kbGUECQBuYW1lX2hhc2i00dtusU3CqQMKAG5ldHdvcmtfaWR9LTmpCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:lime_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWShAgAACAQAbmFtZRUAbWluZWNyYWZ0OmxpbWVfY2FuZGxlBAkAbmFtZV9oYXNokcmrw5xvz7ADCgBuZXR3b3JrX2lkIAUu6QoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:pink_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSiAgAACAQAbmFtZRUAbWluZWNyYWZ0OnBpbmtfY2FuZGxlBAkAbmFtZV9oYXNoQJdEY4sZ0dwDCgBuZXR3b3JrX2lk23Rn5AoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:gray_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSjAgAACAQAbmFtZRUAbWluZWNyYWZ0OmdyYXlfY2FuZGxlBAkAbmFtZV9oYXNoS5poSo9wBDEDCgBuZXR3b3JrX2lk3trRCAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:light_gray_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSkAgAACAQAbmFtZRsAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfY2FuZGxlBAkAbmFtZV9oYXNo9ruTZLBNMasDCgBuZXR3b3JrX2lkb6DOegoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:cyan_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSlAgAACAQAbmFtZRUAbWluZWNyYWZ0OmN5YW5fY2FuZGxlBAkAbmFtZV9oYXNoc/M8PNVcjOwDCgBuZXR3b3JrX2lkZoIQOQoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:purple_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSmAgAACAQAbmFtZRcAbWluZWNyYWZ0OnB1cnBsZV9jYW5kbGUECQBuYW1lX2hhc2jaI3xUW0/myQMKAG5ldHdvcmtfaWSnLI2BCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:blue_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSnAgAACAQAbmFtZRUAbWluZWNyYWZ0OmJsdWVfY2FuZGxlBAkAbmFtZV9oYXNoAASSPW6TgQADCgBuZXR3b3JrX2lkrxrjQAoGAHN0YXRlcwMHAGNhbmRsZXMAAAAAAQMAbGl0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:brown_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSoAgAACAQAbmFtZRYAbWluZWNyYWZ0OmJyb3duX2NhbmRsZQQJAG5hbWVfaGFzaDia0l6s1+WYAwoAbmV0d29ya19pZKSkBXYKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:green_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAgAACAQAbmFtZRYAbWluZWNyYWZ0OmdyZWVuX2NhbmRsZQQJAG5hbWVfaGFzaLeFPO1l+fIoAwoAbmV0d29ya19pZBkznDsKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:red_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSqAgAACAQAbmFtZRQAbWluZWNyYWZ0OnJlZF9jYW5kbGUECQBuYW1lX2hhc2jjAQpGf59ZdwMKAG5ldHdvcmtfaWRbb88GCgYAc3RhdGVzAwcAY2FuZGxlcwAAAAABAwBsaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:black_candle", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSrAgAACAQAbmFtZRYAbWluZWNyYWZ0OmJsYWNrX2NhbmRsZQQJAG5hbWVfaGFzaB+wRDpOqREKAwoAbmV0d29ya19pZNnOnuEKBgBzdGF0ZXMDBwBjYW5kbGVzAAAAAAEDAGxpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:crafting_table", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ6AAAACAQAbmFtZRgAbWluZWNyYWZ0OmNyYWZ0aW5nX3RhYmxlBAkAbmFtZV9oYXNoe76VAmjvbpYDCgBuZXR3b3JrX2lkwCxwaAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:cartography_table", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTHAQAACAQAbmFtZRsAbWluZWNyYWZ0OmNhcnRvZ3JhcGh5X3RhYmxlBAkAbmFtZV9oYXNomaWiiD/znP8DCgBuZXR3b3JrX2lkI6FzMwoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:fletching_table", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTIAQAACAQAbmFtZRkAbWluZWNyYWZ0OmZsZXRjaGluZ190YWJsZQQJAG5hbWVfaGFzaPFibh8unKyUAwoAbmV0d29ya19pZJ2mW0oKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:smithing_table", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTJAQAACAQAbmFtZRgAbWluZWNyYWZ0OnNtaXRoaW5nX3RhYmxlBAkAbmFtZV9oYXNo4tFES2xOXEYDCgBuZXR3b3JrX2lkXWMBzQoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:beehive", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAQAACAQAbmFtZREAbWluZWNyYWZ0OmJlZWhpdmUECQBuYW1lX2hhc2hCcqn12UbNpwMKAG5ldHdvcmtfaWR/idcaCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAMLAGhvbmV5X2xldmVsAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:suspicious_sand", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQQAwAACAQAbmFtZRkAbWluZWNyYWZ0OnN1c3BpY2lvdXNfc2FuZAQJAG5hbWVfaGFzaL67QsuvLP00AwoAbmV0d29ya19pZKnkaIAKBgBzdGF0ZXMDEABicnVzaGVkX3Byb2dyZXNzAAAAAAEHAGhhbmdpbmcBAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:suspicious_gravel", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ8AwAACAQAbmFtZRsAbWluZWNyYWZ0OnN1c3BpY2lvdXNfZ3JhdmVsBAkAbmFtZV9oYXNoJSVbGNk7C3oDCgBuZXR3b3JrX2lkvIEJAAoGAHN0YXRlcwMQAGJydXNoZWRfcHJvZ3Jlc3MAAAAAAQcAaGFuZ2luZwEAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:campfire" + }, + { + "id": "minecraft:soul_campfire" + }, + { + "id": "minecraft:furnace", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ9AAAACAQAbmFtZREAbWluZWNyYWZ0OmZ1cm5hY2UECQBuYW1lX2hhc2ioOQrludYY8wMKAG5ldHdvcmtfaWRZxnDOCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:blast_furnace", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTDAQAACAQAbmFtZRcAbWluZWNyYWZ0OmJsYXN0X2Z1cm5hY2UECQBuYW1lX2hhc2ivDbnjkpGm5QMKAG5ldHdvcmtfaWTcEbV/CgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:smoker", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTFAQAACAQAbmFtZRAAbWluZWNyYWZ0OnNtb2tlcgQJAG5hbWVfaGFzaJd1rDMkRWomAwoAbmV0d29ya19pZGWswMwKBgBzdGF0ZXMIHABtaW5lY3JhZnQ6Y2FyZGluYWxfZGlyZWN0aW9uBQBzb3V0aAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:respawn_anchor", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQPAgAACAQAbmFtZRgAbWluZWNyYWZ0OnJlc3Bhd25fYW5jaG9yBAkAbmFtZV9oYXNoZOdcjW05qigDCgBuZXR3b3JrX2lkmhMcaQoGAHN0YXRlcwMVAHJlc3Bhd25fYW5jaG9yX2NoYXJnZQAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:brewing_stand" + }, + { + "id": "minecraft:anvil", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSRAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmFudmlsBAkAbmFtZV9oYXNoNqB3fgcUCbwDCgBuZXR3b3JrX2lkqXzNjwoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAHNvdXRoAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:chipped_anvil", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS+BAAACAQAbmFtZRcAbWluZWNyYWZ0OmNoaXBwZWRfYW52aWwECQBuYW1lX2hhc2ge+QY3vlS/eQMKAG5ldHdvcmtfaWRJ15iUCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:damaged_anvil", + "block_state_b64": "CgAAAwgAYmxvY2tfaWS/BAAACAQAbmFtZRcAbWluZWNyYWZ0OmRhbWFnZWRfYW52aWwECQBuYW1lX2hhc2imJ12Be2V8+AMKAG5ldHdvcmtfaWRh5SHkCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:grindstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTCAQAACAQAbmFtZRQAbWluZWNyYWZ0OmdyaW5kc3RvbmUECQBuYW1lX2hhc2id56zc0nk99wMKAG5ldHdvcmtfaWS4Es07CgYAc3RhdGVzCAoAYXR0YWNobWVudAgAc3RhbmRpbmcDCQBkaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:enchanting_table", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR0AAAACAQAbmFtZRoAbWluZWNyYWZ0OmVuY2hhbnRpbmdfdGFibGUECQBuYW1lX2hhc2jgIx24VLvMvwMKAG5ldHdvcmtfaWRliFFJCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:bookshelf", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQvAAAACAQAbmFtZRMAbWluZWNyYWZ0OmJvb2tzaGVsZgQJAG5hbWVfaGFzaDU04DrgJCS9AwoAbmV0d29ya19pZBcWwIwKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:chiseled_bookshelf", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQNAwAACAQAbmFtZRwAbWluZWNyYWZ0OmNoaXNlbGVkX2Jvb2tzaGVsZgQJAG5hbWVfaGFzaNXDBnsIsywYAwoAbmV0d29ya19pZIprt5IKBgBzdGF0ZXMDDABib29rc19zdG9yZWQAAAAAAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:lectern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTBAQAACAQAbmFtZREAbWluZWNyYWZ0OmxlY3Rlcm4ECQBuYW1lX2hhc2j5Z4Mmi/1QxAMKAG5ldHdvcmtfaWR4JfDHCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAc291dGgBCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:cauldron" + }, + { + "id": "minecraft:composter", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTUAQAACAQAbmFtZRMAbWluZWNyYWZ0OmNvbXBvc3RlcgQJAG5hbWVfaGFzaPAADHptzeWJAwoAbmV0d29ya19pZHIL6i4KBgBzdGF0ZXMDFABjb21wb3N0ZXJfZmlsbF9sZXZlbAAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:chest", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ2AAAACAQAbmFtZQ8AbWluZWNyYWZ0OmNoZXN0BAkAbmFtZV9oYXNog9ozMxlcA88DCgBuZXR3b3JrX2lkDkOFvAoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:trapped_chest", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSSAAAACAQAbmFtZRcAbWluZWNyYWZ0OnRyYXBwZWRfY2hlc3QECQBuYW1lX2hhc2g2qpF9stsEjgMKAG5ldHdvcmtfaWTjJWYxCgYAc3RhdGVzCBwAbWluZWNyYWZ0OmNhcmRpbmFsX2RpcmVjdGlvbgUAbm9ydGgAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:ender_chest", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSCAAAACAQAbmFtZRUAbWluZWNyYWZ0OmVuZGVyX2NoZXN0BAkAbmFtZV9oYXNohEZzOFdg0WUDCgBuZXR3b3JrX2lkx4jiSQoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:barrel", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTKAQAACAQAbmFtZRAAbWluZWNyYWZ0OmJhcnJlbAQJAG5hbWVfaGFzaHDkRPGymiRqAwoAbmV0d29ya19pZPnxzgsKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAAAAAAEIAG9wZW5fYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:undyed_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTNAAAACAQAbmFtZRwAbWluZWNyYWZ0OnVuZHllZF9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaOC9mypm/MlBAwoAbmV0d29ya19pZJ8rxp0KBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:white_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTaAAAACAQAbmFtZRsAbWluZWNyYWZ0OndoaXRlX3NodWxrZXJfYm94BAkAbmFtZV9oYXNosK79m1rPUBwDCgBuZXR3b3JrX2lkjrET6goGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:light_gray_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRrAwAACAQAbmFtZSAAbWluZWNyYWZ0OmxpZ2h0X2dyYXlfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2iBe5zq7PxHmgMKAG5ldHdvcmtfaWSCVJv0CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:gray_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRqAwAACAQAbmFtZRoAbWluZWNyYWZ0OmdyYXlfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2ga2s8ctjHUhgMKAG5ldHdvcmtfaWS3WMsWCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:black_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRyAwAACAQAbmFtZRsAbWluZWNyYWZ0OmJsYWNrX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoPm03OZphrp8DCgBuZXR3b3JrX2lkXHztNAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:brown_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRvAwAACAQAbmFtZRsAbWluZWNyYWZ0OmJyb3duX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoT3DD6qAL9cADCgBuZXR3b3JrX2lkaXxpYQoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:red_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRxAwAACAQAbmFtZRkAbWluZWNyYWZ0OnJlZF9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaMIlKSCzqSZoAwoAbmV0d29ya19pZNrf+icKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:orange_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRkAwAACAQAbmFtZRwAbWluZWNyYWZ0Om9yYW5nZV9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaG2MAXU67wGrAwoAbmV0d29ya19pZGoO05gKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:yellow_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRnAwAACAQAbmFtZRwAbWluZWNyYWZ0OnllbGxvd19zaHVsa2VyX2JveAQJAG5hbWVfaGFzaIsLwQHYjcIEAwoAbmV0d29ya19pZBCBSiYKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:lime_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRoAwAACAQAbmFtZRoAbWluZWNyYWZ0OmxpbWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2hUwBkg+faUGAMKAG5ldHdvcmtfaWRJeKqqCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:green_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRwAwAACAQAbmFtZRsAbWluZWNyYWZ0OmdyZWVuX3NodWxrZXJfYm94BAkAbmFtZV9oYXNoZgUeT3LupLUDCgBuZXR3b3JrX2lkzJiohQoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:cyan_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRsAwAACAQAbmFtZRoAbWluZWNyYWZ0OmN5YW5fc2h1bGtlcl9ib3gECQBuYW1lX2hhc2gSfbjteXg5yAMKAG5ldHdvcmtfaWTHeliECgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:light_blue_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRmAwAACAQAbmFtZSAAbWluZWNyYWZ0OmxpZ2h0X2JsdWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2h0VFCX0qsRxQMKAG5ldHdvcmtfaWQXD8U0CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:blue_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRuAwAACAQAbmFtZRoAbWluZWNyYWZ0OmJsdWVfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2hn9gS0XIe6rAMKAG5ldHdvcmtfaWTO4PJaCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:purple_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRtAwAACAQAbmFtZRwAbWluZWNyYWZ0OnB1cnBsZV9zaHVsa2VyX2JveAQJAG5hbWVfaGFzaEV/lkNPxRDdAwoAbmV0d29ya19pZFK25GAKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:magenta_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRlAwAACAQAbmFtZR0AbWluZWNyYWZ0Om1hZ2VudGFfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2iqWM7IJHxcFgMKAG5ldHdvcmtfaWTyyudTCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:pink_shulker_box", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRpAwAACAQAbmFtZRoAbWluZWNyYWZ0OnBpbmtfc2h1bGtlcl9ib3gECQBuYW1lX2hhc2in1tkJ1GNcZgMKAG5ldHdvcmtfaWQOEGXjCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:armor_stand" + }, + { + "id": "minecraft:noteblock", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQZAAAACAQAbmFtZRMAbWluZWNyYWZ0Om5vdGVibG9jawQJAG5hbWVfaGFzaHPA8dBBH0UaAwoAbmV0d29ya19pZH1U5QkKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:jukebox", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRUAAAACAQAbmFtZREAbWluZWNyYWZ0Omp1a2Vib3gECQBuYW1lX2hhc2ieAIPExf/ZfgMKAG5ldHdvcmtfaWSmR7JfCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "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:music_disc_creator" + }, + { + "id": "minecraft:music_disc_creator_music_box" + }, + { + "id": "minecraft:music_disc_precipice" + }, + { + "id": "minecraft:disc_fragment_5" + }, + { + "id": "minecraft:glowstone_dust" + }, + { + "id": "minecraft:glowstone", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRZAAAACAQAbmFtZRMAbWluZWNyYWZ0Omdsb3dzdG9uZQQJAG5hbWVfaGFzaFYqXNkefIlPAwoAbmV0d29ya19pZGT7WYYKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:redstone_lamp", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR7AAAACAQAbmFtZRcAbWluZWNyYWZ0OnJlZHN0b25lX2xhbXAECQBuYW1lX2hhc2hJ9V80caPvEgMKAG5ldHdvcmtfaWRvNPwnCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:sea_lantern", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSpAAAACAQAbmFtZRUAbWluZWNyYWZ0OnNlYV9sYW50ZXJuBAkAbmFtZV9oYXNoLPsv1TX9M+QDCgBuZXR3b3JrX2lk1PPVyAoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "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": "CgAAAwgAYmxvY2tfaWSKAAAACAQAbmFtZRAAbWluZWNyYWZ0OmJlYWNvbgQJAG5hbWVfaGFzaACwhhfSkdkHAwoAbmV0d29ya19pZF8jfiEKBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:bell", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTNAQAACAQAbmFtZQ4AbWluZWNyYWZ0OmJlbGwECQBuYW1lX2hhc2iPqsgDXRcsxAMKAG5ldHdvcmtfaWT7zhOoCgYAc3RhdGVzCAoAYXR0YWNobWVudAgAc3RhbmRpbmcDCQBkaXJlY3Rpb24AAAAAAQoAdG9nZ2xlX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:conduit", + "block_state_b64": "CgAAAwgAYmxvY2tfaWScAQAACAQAbmFtZREAbWluZWNyYWZ0OmNvbmR1aXQECQBuYW1lX2hhc2jqxKAxq2EaWQMKAG5ldHdvcmtfaWTWcBVnCgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:stonecutter_block", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTEAQAACAQAbmFtZRsAbWluZWNyYWZ0OnN0b25lY3V0dGVyX2Jsb2NrBAkAbmFtZV9oYXNoQAXTbAM3MeYDCgBuZXR3b3JrX2lkWS4RjAoGAHN0YXRlcwgcAG1pbmVjcmFmdDpjYXJkaW5hbF9kaXJlY3Rpb24FAG5vcnRoAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:coal" + }, + { + "id": "minecraft:charcoal" + }, + { + "id": "minecraft:diamond" + }, + { + "id": "minecraft:iron_nugget" + }, + { + "id": "minecraft:raw_iron" + }, + { + "id": "minecraft:raw_gold" + }, + { + "id": "minecraft:raw_copper" + }, + { + "id": "minecraft:copper_ingot" + }, + { + "id": "minecraft:iron_ingot" + }, + { + "id": "minecraft:netherite_scrap" + }, + { + "id": "minecraft:netherite_ingot" + }, + { + "id": "minecraft:gold_nugget" + }, + { + "id": "minecraft:gold_ingot" + }, + { + "id": "minecraft:emerald" + }, + { + "id": "minecraft:quartz" + }, + { + "id": "minecraft:clay_ball" + }, + { + "id": "minecraft:brick" + }, + { + "id": "minecraft:netherbrick" + }, + { + "id": "minecraft:prismarine_shard" + }, + { + "id": "minecraft:amethyst_shard" + }, + { + "id": "minecraft:prismarine_crystals" + }, + { + "id": "minecraft:nautilus_shell" + }, + { + "id": "minecraft:heart_of_the_sea" + }, + { + "id": "minecraft:turtle_scute" + }, + { + "id": "minecraft:armadillo_scute" + }, + { + "id": "minecraft:phantom_membrane" + }, + { + "id": "minecraft:string" + }, + { + "id": "minecraft:feather" + }, + { + "id": "minecraft:flint" + }, + { + "id": "minecraft:gunpowder" + }, + { + "id": "minecraft:leather" + }, + { + "id": "minecraft:rabbit_hide" + }, + { + "id": "minecraft:rabbit_foot" + }, + { + "id": "minecraft:fire_charge" + }, + { + "id": "minecraft:blaze_rod" + }, + { + "id": "minecraft:breeze_rod" + }, + { + "id": "minecraft:heavy_core", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ7AgAACAQAbmFtZRQAbWluZWNyYWZ0OmhlYXZ5X2NvcmUECQBuYW1lX2hhc2hhz/uNCtrC2QMKAG5ldHdvcmtfaWRaFu+8CgYAc3RhdGVzAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "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/q5cEA0hmQMKAG5ldHdvcmtfaWQ2eM8kCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:lightning_rod", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ3AgAACAQAbmFtZRcAbWluZWNyYWZ0OmxpZ2h0bmluZ19yb2QECQBuYW1lX2hhc2ioXQF1xvfHNQMKAG5ldHdvcmtfaWRLuHyACgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:end_crystal" + }, + { + "id": "minecraft:paper" + }, + { + "id": "minecraft:book" + }, + { + "id": "minecraft:writable_book" + }, + { + "id": "minecraft:trial_key" + }, + { + "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: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" + }, + { + "id": "minecraft:spruce_boat" + }, + { + "id": "minecraft:birch_boat" + }, + { + "id": "minecraft:jungle_boat" + }, + { + "id": "minecraft:acacia_boat" + }, + { + "id": "minecraft:dark_oak_boat" + }, + { + "id": "minecraft:mangrove_boat" + }, + { + "id": "minecraft:cherry_boat" + }, + { + "id": "minecraft:bamboo_raft" + }, + { + "id": "minecraft:oak_chest_boat" + }, + { + "id": "minecraft:spruce_chest_boat" + }, + { + "id": "minecraft:birch_chest_boat" + }, + { + "id": "minecraft:jungle_chest_boat" + }, + { + "id": "minecraft:acacia_chest_boat" + }, + { + "id": "minecraft:dark_oak_chest_boat" + }, + { + "id": "minecraft:mangrove_chest_boat" + }, + { + "id": "minecraft:cherry_chest_boat" + }, + { + "id": "minecraft:bamboo_chest_raft" + }, + { + "id": "minecraft:rail", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRCAAAACAQAbmFtZQ4AbWluZWNyYWZ0OnJhaWwECQBuYW1lX2hhc2hUzmhUXYJDUQMKAG5ldHdvcmtfaWR+Sp6YCgYAc3RhdGVzAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:golden_rail", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQbAAAACAQAbmFtZRUAbWluZWNyYWZ0OmdvbGRlbl9yYWlsBAkAbmFtZV9oYXNoOoV5MaKipoUDCgBuZXR3b3JrX2lkfAcxLwoGAHN0YXRlcwENAHJhaWxfZGF0YV9iaXQAAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:detector_rail", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQcAAAACAQAbmFtZRcAbWluZWNyYWZ0OmRldGVjdG9yX3JhaWwECQBuYW1lX2hhc2gVUk31qOysUQMKAG5ldHdvcmtfaWRVW/aICgYAc3RhdGVzAQ0AcmFpbF9kYXRhX2JpdAADDgByYWlsX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:activator_rail", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR+AAAACAQAbmFtZRgAbWluZWNyYWZ0OmFjdGl2YXRvcl9yYWlsBAkAbmFtZV9oYXNosIL91qriCRkDCgBuZXR3b3JrX2lkZfckmwoGAHN0YXRlcwENAHJhaWxfZGF0YV9iaXQAAw4AcmFpbF9kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "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": "CgAAAwgAYmxvY2tfaWSYAAAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZHN0b25lX2Jsb2NrBAkAbmFtZV9oYXNoRhULL0r8o0sDCgBuZXR3b3JrX2lklayOHgoGAHN0YXRlcwADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:redstone_torch", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRMAAAACAQAbmFtZRgAbWluZWNyYWZ0OnJlZHN0b25lX3RvcmNoBAkAbmFtZV9oYXNoizFRjpYMIDgDCgBuZXR3b3JrX2lkuHz7yAoGAHN0YXRlcwgWAHRvcmNoX2ZhY2luZ19kaXJlY3Rpb24HAHVua25vd24AAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:lever", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRFAAAACAQAbmFtZQ8AbWluZWNyYWZ0OmxldmVyBAkAbmFtZV9oYXNoGMJeLJsUMLYDCgBuZXR3b3JrX2lkEF/GuAoGAHN0YXRlcwgPAGxldmVyX2RpcmVjdGlvbg4AZG93bl9lYXN0X3dlc3QBCABvcGVuX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:wooden_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAAAACAQAbmFtZRcAbWluZWNyYWZ0Ondvb2Rlbl9idXR0b24ECQBuYW1lX2hhc2hR7PgSTQt0sQMKAG5ldHdvcmtfaWSU07kYCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:spruce_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSPAQAACAQAbmFtZRcAbWluZWNyYWZ0OnNwcnVjZV9idXR0b24ECQBuYW1lX2hhc2jBW9Z8aYE7YQMKAG5ldHdvcmtfaWTkUIGuCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:birch_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSMAQAACAQAbmFtZRYAbWluZWNyYWZ0OmJpcmNoX2J1dHRvbgQJAG5hbWVfaGFzaJXYgGuSHbTwAwoAbmV0d29ya19pZGWp3yoKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:jungle_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSOAQAACAQAbmFtZRcAbWluZWNyYWZ0Omp1bmdsZV9idXR0b24ECQBuYW1lX2hhc2iCgNANcJs+BQMKAG5ldHdvcmtfaWT9fImWCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:acacia_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSLAQAACAQAbmFtZRcAbWluZWNyYWZ0OmFjYWNpYV9idXR0b24ECQBuYW1lX2hhc2gVvmcT7LTO0wMKAG5ldHdvcmtfaWRQnxIJCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:dark_oak_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSNAQAACAQAbmFtZRkAbWluZWNyYWZ0OmRhcmtfb2FrX2J1dHRvbgQJAG5hbWVfaGFzaIV10ZGGrCIEAwoAbmV0d29ya19pZN5vAmIKBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:mangrove_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTmAgAACAQAbmFtZRkAbWluZWNyYWZ0Om1hbmdyb3ZlX2J1dHRvbgQJAG5hbWVfaGFzaNzeYYKLgOzJAwoAbmV0d29ya19pZAFEGQ0KBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:cherry_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQRAwAACAQAbmFtZRcAbWluZWNyYWZ0OmNoZXJyeV9idXR0b24ECQBuYW1lX2hhc2j2/IHjeAbUcwMKAG5ldHdvcmtfaWRJ1irQCgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:bamboo_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT+AgAACAQAbmFtZRcAbWluZWNyYWZ0OmJhbWJvb19idXR0b24ECQBuYW1lX2hhc2j7AddMi+6nsgMKAG5ldHdvcmtfaWSa9w4/CgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:stone_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRNAAAACAQAbmFtZRYAbWluZWNyYWZ0OnN0b25lX2J1dHRvbgQJAG5hbWVfaGFzaM4ejMctmvohAwoAbmV0d29ya19pZMw+aC0KBgBzdGF0ZXMBEgBidXR0b25fcHJlc3NlZF9iaXQAAxAAZmFjaW5nX2RpcmVjdGlvbgAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:crimson_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQDAgAACAQAbmFtZRgAbWluZWNyYWZ0OmNyaW1zb25fYnV0dG9uBAkAbmFtZV9oYXNofnjYHaYIeWgDCgBuZXR3b3JrX2lk+n1vyQoGAHN0YXRlcwESAGJ1dHRvbl9wcmVzc2VkX2JpdAADEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:warped_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQEAgAACAQAbmFtZRcAbWluZWNyYWZ0OndhcnBlZF9idXR0b24ECQBuYW1lX2hhc2jwkV2EU6Cn1QMKAG5ldHdvcmtfaWTnHnk1CgYAc3RhdGVzARIAYnV0dG9uX3ByZXNzZWRfYml0AAMQAGZhY2luZ19kaXJlY3Rpb24AAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:polished_blackstone_button", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQnAgAACAQAbmFtZSQAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfYnV0dG9uBAkAbmFtZV9oYXNojmxzQKS0S/EDCgBuZXR3b3JrX2lkDtQ95woGAHN0YXRlcwESAGJ1dHRvbl9wcmVzc2VkX2JpdAADEABmYWNpbmdfZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:tripwire_hook", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSDAAAACAQAbmFtZRcAbWluZWNyYWZ0OnRyaXB3aXJlX2hvb2sECQBuYW1lX2hhc2gQdp+oGZLNnAMKAG5ldHdvcmtfaWSy+1KJCgYAc3RhdGVzAQwAYXR0YWNoZWRfYml0AAMJAGRpcmVjdGlvbgAAAAABCwBwb3dlcmVkX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:wooden_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRIAAAACAQAbmFtZR8AbWluZWNyYWZ0Ondvb2Rlbl9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaGkGs5kCuA74AwoAbmV0d29ya19pZDRzPNwKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:spruce_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSZAQAACAQAbmFtZR8AbWluZWNyYWZ0OnNwcnVjZV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaNmwuq549fJKAwoAbmV0d29ya19pZLQMCw0KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:birch_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSWAQAACAQAbmFtZR4AbWluZWNyYWZ0OmJpcmNoX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNorQkT9kDdlTwDCgBuZXR3b3JrX2lkH0G97AoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:jungle_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSYAQAACAQAbmFtZR8AbWluZWNyYWZ0Omp1bmdsZV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaJ7DcteCkb8/AwoAbmV0d29ya19pZLdPBSAKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:acacia_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSVAQAACAQAbmFtZR8AbWluZWNyYWZ0OmFjYWNpYV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaC2frZtfoYqCAwoAbmV0d29ya19pZIDdI18KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:dark_oak_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSXAQAACAQAbmFtZSEAbWluZWNyYWZ0OmRhcmtfb2FrX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoHUCJsTy52pwDCgBuZXR3b3JrX2lkKpi8rAoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:mangrove_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTpAgAACAQAbmFtZSEAbWluZWNyYWZ0Om1hbmdyb3ZlX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoiDsTfJaX100DCgBuZXR3b3JrX2lkuwWDyQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:cherry_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQZAwAACAQAbmFtZR8AbWluZWNyYWZ0OmNoZXJyeV9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaALMqYEZDUQHAwoAbmV0d29ya19pZPNT+r0KBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:bamboo_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQBAwAACAQAbmFtZR8AbWluZWNyYWZ0OmJhbWJvb19wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaNvxJ7NIAaqlAwoAbmV0d29ya19pZIZ8XnYKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:crimson_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQFAgAACAQAbmFtZSAAbWluZWNyYWZ0OmNyaW1zb25fcHJlc3N1cmVfcGxhdGUECQBuYW1lX2hhc2hqBDVDAd31/gMKAG5ldHdvcmtfaWRmV18LCgYAc3RhdGVzAw8AcmVkc3RvbmVfc2lnbmFsAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:warped_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQGAgAACAQAbmFtZR8AbWluZWNyYWZ0OndhcnBlZF9wcmVzc3VyZV9wbGF0ZQQJAG5hbWVfaGFzaBxFoQksWtYUAwoAbmV0d29ya19pZJVRoIcKBgBzdGF0ZXMDDwByZWRzdG9uZV9zaWduYWwAAAAAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:stone_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWRGAAAACAQAbmFtZR4AbWluZWNyYWZ0OnN0b25lX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNounJuTBUTrU8DCgBuZXR3b3JrX2lkjDydwQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:light_weighted_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSTAAAACAQAbmFtZScAbWluZWNyYWZ0OmxpZ2h0X3dlaWdodGVkX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoOyOJkNxLtkEDCgBuZXR3b3JrX2lkrr2AjgoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:heavy_weighted_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSUAAAACAQAbmFtZScAbWluZWNyYWZ0OmhlYXZ5X3dlaWdodGVkX3ByZXNzdXJlX3BsYXRlBAkAbmFtZV9oYXNoltgDmDvTajUDCgBuZXR3b3JrX2lkFxVKuQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:polished_blackstone_pressure_plate", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAgAACAQAbmFtZSwAbWluZWNyYWZ0OnBvbGlzaGVkX2JsYWNrc3RvbmVfcHJlc3N1cmVfcGxhdGUECQBuYW1lX2hhc2h65Ci6/CeGqwMKAG5ldHdvcmtfaWTaSW5xCgYAc3RhdGVzAw8AcmVkc3RvbmVfc2lnbmFsAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:observer", + "block_state_b64": "CgAAAwgAYmxvY2tfaWT7AAAACAQAbmFtZRIAbWluZWNyYWZ0Om9ic2VydmVyBAkAbmFtZV9oYXNoYhlh1lpmHTgDCgBuZXR3b3JrX2lkQEh55goGAHN0YXRlcwgaAG1pbmVjcmFmdDpmYWNpbmdfZGlyZWN0aW9uBABkb3duAQsAcG93ZXJlZF9iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:daylight_detector", + "block_state_b64": "CgAAAwgAYmxvY2tfaWSXAAAACAQAbmFtZRsAbWluZWNyYWZ0OmRheWxpZ2h0X2RldGVjdG9yBAkAbmFtZV9oYXNoV0F0s7B7PVgDCgBuZXR3b3JrX2lkri5afQoGAHN0YXRlcwMPAHJlZHN0b25lX3NpZ25hbAAAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:repeater" + }, + { + "id": "minecraft:comparator" + }, + { + "id": "minecraft:hopper" + }, + { + "id": "minecraft:dropper", + "block_state_b64": "CgAAAwgAYmxvY2tfaWR9AAAACAQAbmFtZREAbWluZWNyYWZ0OmRyb3BwZXIECQBuYW1lX2hhc2joXP7XqU0l3QMKAG5ldHdvcmtfaWQfQN6zCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgMAAAABDQB0cmlnZ2VyZWRfYml0AAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:dispenser", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQXAAAACAQAbmFtZRMAbWluZWNyYWZ0OmRpc3BlbnNlcgQJAG5hbWVfaGFzaP1RR+zAbYP2AwoAbmV0d29ya19pZGAayD0KBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAwAAAAENAHRyaWdnZXJlZF9iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:crafter", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQ4AgAACAQAbmFtZREAbWluZWNyYWZ0OmNyYWZ0ZXIECQBuYW1lX2hhc2iLCT/rJmRN8QMKAG5ldHdvcmtfaWTPTbvrCgYAc3RhdGVzAQgAY3JhZnRpbmcACAsAb3JpZW50YXRpb24JAGRvd25fZWFzdAENAHRyaWdnZXJlZF9iaXQAAAMHAHZlcnNpb24HHhUBAA==" + }, + { + "id": "minecraft:piston", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQhAAAACAQAbmFtZRAAbWluZWNyYWZ0OnBpc3RvbgQJAG5hbWVfaGFzaDs3AFh1fL0uAwoAbmV0d29ya19pZLD/5XQKBgBzdGF0ZXMDEABmYWNpbmdfZGlyZWN0aW9uAQAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:sticky_piston", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQdAAAACAQAbmFtZRcAbWluZWNyYWZ0OnN0aWNreV9waXN0b24ECQBuYW1lX2hhc2hPFJFJSiJ0ZQMKAG5ldHdvcmtfaWT/MzCJCgYAc3RhdGVzAxAAZmFjaW5nX2RpcmVjdGlvbgEAAAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:tnt", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQuAAAACAQAbmFtZQ0AbWluZWNyYWZ0OnRudAQJAG5hbWVfaGFzaEYOHwCvJH29AwoAbmV0d29ya19pZAXzHyUKBgBzdGF0ZXMBCwBleHBsb2RlX2JpdAAAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:name_tag" + }, + { + "id": "minecraft:loom", + "block_state_b64": "CgAAAwgAYmxvY2tfaWTLAQAACAQAbmFtZQ4AbWluZWNyYWZ0Omxvb20ECQBuYW1lX2hhc2i7DKjAXNq8TAMKAG5ldHdvcmtfaWR/49HXCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:banner", + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 8, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 7, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 15, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 12, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 14, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 1, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 4, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 5, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 13, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 9, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 3, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 11, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 10, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 2, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 6, + "nbt_b64": "CgAAAwQAVHlwZQAAAAAA" + }, + { + "id": "minecraft:banner", + "damage": 15, + "nbt_b64": "CgAAAwQAVHlwZQEAAAAA" + }, + { + "id": "minecraft:creeper_banner_pattern" + }, + { + "id": "minecraft:skull_banner_pattern" + }, + { + "id": "minecraft:flower_banner_pattern" + }, + { + "id": "minecraft:mojang_banner_pattern" + }, + { + "id": "minecraft:field_masoned_banner_pattern" + }, + { + "id": "minecraft:bordure_indented_banner_pattern" + }, + { + "id": "minecraft:piglin_banner_pattern" + }, + { + "id": "minecraft:globe_banner_pattern" + }, + { + "id": "minecraft:flow_banner_pattern" + }, + { + "id": "minecraft:guster_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:flow_pottery_sherd" + }, + { + "id": "minecraft:friend_pottery_sherd" + }, + { + "id": "minecraft:guster_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:scrape_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:flow_armor_trim_smithing_template" + }, + { + "id": "minecraft:bolt_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": "CgAAAwgAYmxvY2tfaWTuAQAACAQAbmFtZRAAbWluZWNyYWZ0OnRhcmdldAQJAG5hbWVfaGFzaJc66SVbYlaxAwoAbmV0d29ya19pZPBozs0KBgBzdGF0ZXMAAwcAdmVyc2lvbgceFQEA" + }, + { + "id": "minecraft:decorated_pot", + "block_state_b64": "CgAAAwgAYmxvY2tfaWQmAwAACAQAbmFtZRcAbWluZWNyYWZ0OmRlY29yYXRlZF9wb3QECQBuYW1lX2hhc2jjQgckn8VTvwMKAG5ldHdvcmtfaWRwvkUUCgYAc3RhdGVzAwkAZGlyZWN0aW9uAAAAAAADBwB2ZXJzaW9uBx4VAQA=" + }, + { + "id": "minecraft:lodestone_compass" + }, + { + "id": "minecraft:wither_spawn_egg" + }, + { + "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 95d00c246..90ca16be3 100644 Binary files a/core/src/main/resources/bedrock/entity_identifiers.dat and b/core/src/main/resources/bedrock/entity_identifiers.dat differ diff --git a/core/src/main/resources/bedrock/runtime_item_states.1_21_20.json b/core/src/main/resources/bedrock/runtime_item_states.1_21_20.json new file mode 100644 index 000000000..72c682293 --- /dev/null +++ b/core/src/main/resources/bedrock/runtime_item_states.1_21_20.json @@ -0,0 +1,6794 @@ +[ + { + "name": "minecraft:acacia_boat", + "id": 388 + }, + { + "name": "minecraft:acacia_button", + "id": -140 + }, + { + "name": "minecraft:acacia_chest_boat", + "id": 662 + }, + { + "name": "minecraft:acacia_door", + "id": 573 + }, + { + "name": "minecraft:acacia_double_slab", + "id": -812 + }, + { + "name": "minecraft:acacia_fence", + "id": -575 + }, + { + "name": "minecraft:acacia_fence_gate", + "id": 187 + }, + { + "name": "minecraft:acacia_hanging_sign", + "id": -504 + }, + { + "name": "minecraft:acacia_leaves", + "id": 161 + }, + { + "name": "minecraft:acacia_log", + "id": 162 + }, + { + "name": "minecraft:acacia_planks", + "id": -742 + }, + { + "name": "minecraft:acacia_pressure_plate", + "id": -150 + }, + { + "name": "minecraft:acacia_sapling", + "id": -828 + }, + { + "name": "minecraft:acacia_sign", + "id": 596 + }, + { + "name": "minecraft:acacia_slab", + "id": -807 + }, + { + "name": "minecraft:acacia_stairs", + "id": 163 + }, + { + "name": "minecraft:acacia_standing_sign", + "id": -190 + }, + { + "name": "minecraft:acacia_trapdoor", + "id": -145 + }, + { + "name": "minecraft:acacia_wall_sign", + "id": -191 + }, + { + "name": "minecraft:acacia_wood", + "id": -817 + }, + { + "name": "minecraft:activator_rail", + "id": 126 + }, + { + "name": "minecraft:agent_spawn_egg", + "id": 498 + }, + { + "name": "minecraft:air", + "id": -158 + }, + { + "name": "minecraft:allay_spawn_egg", + "id": 651 + }, + { + "name": "minecraft:allium", + "id": -831 + }, + { + "name": "minecraft:allow", + "id": 210 + }, + { + "name": "minecraft:amethyst_block", + "id": -327 + }, + { + "name": "minecraft:amethyst_cluster", + "id": -329 + }, + { + "name": "minecraft:amethyst_shard", + "id": 644 + }, + { + "name": "minecraft:ancient_debris", + "id": -271 + }, + { + "name": "minecraft:andesite", + "id": -594 + }, + { + "name": "minecraft:andesite_double_slab", + "id": -920 + }, + { + "name": "minecraft:andesite_slab", + "id": -893 + }, + { + "name": "minecraft:andesite_stairs", + "id": -171 + }, + { + "name": "minecraft:angler_pottery_sherd", + "id": 676 + }, + { + "name": "minecraft:anvil", + "id": 145 + }, + { + "name": "minecraft:apple", + "id": 257 + }, + { + "name": "minecraft:archer_pottery_sherd", + "id": 677 + }, + { + "name": "minecraft:armadillo_scute", + "id": 722 + }, + { + "name": "minecraft:armadillo_spawn_egg", + "id": 721 + }, + { + "name": "minecraft:armor_stand", + "id": 569 + }, + { + "name": "minecraft:arms_up_pottery_sherd", + "id": 678 + }, + { + "name": "minecraft:arrow", + "id": 308 + }, + { + "name": "minecraft:axolotl_bucket", + "id": 377 + }, + { + "name": "minecraft:axolotl_spawn_egg", + "id": 513 + }, + { + "name": "minecraft:azalea", + "id": -337 + }, + { + "name": "minecraft:azalea_leaves", + "id": -324 + }, + { + "name": "minecraft:azalea_leaves_flowered", + "id": -325 + }, + { + "name": "minecraft:azure_bluet", + "id": -832 + }, + { + "name": "minecraft:baked_potato", + "id": 286 + }, + { + "name": "minecraft:balloon", + "id": 618 + }, + { + "name": "minecraft:bamboo", + "id": -163 + }, + { + "name": "minecraft:bamboo_block", + "id": -527 + }, + { + "name": "minecraft:bamboo_button", + "id": -511 + }, + { + "name": "minecraft:bamboo_chest_raft", + "id": 674 + }, + { + "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": 673 + }, + { + "name": "minecraft:bamboo_sapling", + "id": -164 + }, + { + "name": "minecraft:bamboo_sign", + "id": 672 + }, + { + "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": 584 + }, + { + "name": "minecraft:banner_pattern", + "id": 767 + }, + { + "name": "minecraft:barrel", + "id": -203 + }, + { + "name": "minecraft:barrier", + "id": -161 + }, + { + "name": "minecraft:basalt", + "id": -234 + }, + { + "name": "minecraft:bat_spawn_egg", + "id": 463 + }, + { + "name": "minecraft:beacon", + "id": 138 + }, + { + "name": "minecraft:bed", + "id": 427 + }, + { + "name": "minecraft:bedrock", + "id": 7 + }, + { + "name": "minecraft:bee_nest", + "id": -218 + }, + { + "name": "minecraft:bee_spawn_egg", + "id": 505 + }, + { + "name": "minecraft:beef", + "id": 278 + }, + { + "name": "minecraft:beehive", + "id": -219 + }, + { + "name": "minecraft:beetroot", + "id": 290 + }, + { + "name": "minecraft:beetroot_seeds", + "id": 300 + }, + { + "name": "minecraft:beetroot_soup", + "id": 291 + }, + { + "name": "minecraft:bell", + "id": -206 + }, + { + "name": "minecraft:big_dripleaf", + "id": -323 + }, + { + "name": "minecraft:birch_boat", + "id": 385 + }, + { + "name": "minecraft:birch_button", + "id": -141 + }, + { + "name": "minecraft:birch_chest_boat", + "id": 659 + }, + { + "name": "minecraft:birch_door", + "id": 571 + }, + { + "name": "minecraft:birch_double_slab", + "id": -810 + }, + { + "name": "minecraft:birch_fence", + "id": -576 + }, + { + "name": "minecraft:birch_fence_gate", + "id": 184 + }, + { + "name": "minecraft:birch_hanging_sign", + "id": -502 + }, + { + "name": "minecraft:birch_leaves", + "id": -801 + }, + { + "name": "minecraft:birch_log", + "id": -570 + }, + { + "name": "minecraft:birch_planks", + "id": -740 + }, + { + "name": "minecraft:birch_pressure_plate", + "id": -151 + }, + { + "name": "minecraft:birch_sapling", + "id": -826 + }, + { + "name": "minecraft:birch_sign", + "id": 594 + }, + { + "name": "minecraft:birch_slab", + "id": -805 + }, + { + "name": "minecraft:birch_stairs", + "id": 135 + }, + { + "name": "minecraft:birch_standing_sign", + "id": -186 + }, + { + "name": "minecraft:birch_trapdoor", + "id": -146 + }, + { + "name": "minecraft:birch_wall_sign", + "id": -187 + }, + { + "name": "minecraft:birch_wood", + "id": -815 + }, + { + "name": "minecraft:black_candle", + "id": -428 + }, + { + "name": "minecraft:black_candle_cake", + "id": -445 + }, + { + "name": "minecraft:black_carpet", + "id": -611 + }, + { + "name": "minecraft:black_concrete", + "id": -642 + }, + { + "name": "minecraft:black_concrete_powder", + "id": -723 + }, + { + "name": "minecraft:black_dye", + "id": 404 + }, + { + "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": 679 + }, + { + "name": "minecraft:blast_furnace", + "id": -196 + }, + { + "name": "minecraft:blaze_powder", + "id": 439 + }, + { + "name": "minecraft:blaze_rod", + "id": 432 + }, + { + "name": "minecraft:blaze_spawn_egg", + "id": 466 + }, + { + "name": "minecraft:bleach", + "id": 616 + }, + { + "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": 408 + }, + { + "name": "minecraft:blue_glazed_terracotta", + "id": 231 + }, + { + "name": "minecraft:blue_ice", + "id": -11 + }, + { + "name": "minecraft:blue_orchid", + "id": -830 + }, + { + "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": 765 + }, + { + "name": "minecraft:bogged_spawn_egg", + "id": 473 + }, + { + "name": "minecraft:bolt_armor_trim_smithing_template", + "id": 718 + }, + { + "name": "minecraft:bone", + "id": 424 + }, + { + "name": "minecraft:bone_block", + "id": 216 + }, + { + "name": "minecraft:bone_meal", + "id": 420 + }, + { + "name": "minecraft:book", + "id": 396 + }, + { + "name": "minecraft:bookshelf", + "id": 47 + }, + { + "name": "minecraft:border_block", + "id": 212 + }, + { + "name": "minecraft:bordure_indented_banner_pattern", + "id": 603 + }, + { + "name": "minecraft:bow", + "id": 307 + }, + { + "name": "minecraft:bowl", + "id": 329 + }, + { + "name": "minecraft:brain_coral", + "id": -581 + }, + { + "name": "minecraft:brain_coral_block", + "id": -849 + }, + { + "name": "minecraft:brain_coral_fan", + "id": -840 + }, + { + "name": "minecraft:brain_coral_wall_fan", + "id": -904 + }, + { + "name": "minecraft:bread", + "id": 266 + }, + { + "name": "minecraft:breeze_rod", + "id": 261 + }, + { + "name": "minecraft:breeze_spawn_egg", + "id": 512 + }, + { + "name": "minecraft:brewer_pottery_sherd", + "id": 680 + }, + { + "name": "minecraft:brewing_stand", + "id": 441 + }, + { + "name": "minecraft:brick", + "id": 392 + }, + { + "name": "minecraft:brick_block", + "id": 45 + }, + { + "name": "minecraft:brick_double_slab", + "id": -880 + }, + { + "name": "minecraft:brick_slab", + "id": -874 + }, + { + "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": 407 + }, + { + "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": 699 + }, + { + "name": "minecraft:bubble_column", + "id": -160 + }, + { + "name": "minecraft:bubble_coral", + "id": -582 + }, + { + "name": "minecraft:bubble_coral_block", + "id": -850 + }, + { + "name": "minecraft:bubble_coral_fan", + "id": -841 + }, + { + "name": "minecraft:bubble_coral_wall_fan", + "id": -136 + }, + { + "name": "minecraft:bucket", + "id": 368 + }, + { + "name": "minecraft:budding_amethyst", + "id": -328 + }, + { + "name": "minecraft:burn_pottery_sherd", + "id": 681 + }, + { + "name": "minecraft:cactus", + "id": 81 + }, + { + "name": "minecraft:cake", + "id": 426 + }, + { + "name": "minecraft:calcite", + "id": -326 + }, + { + "name": "minecraft:calibrated_sculk_sensor", + "id": -580 + }, + { + "name": "minecraft:camel_spawn_egg", + "id": 675 + }, + { + "name": "minecraft:camera", + "id": 613 + }, + { + "name": "minecraft:campfire", + "id": 608 + }, + { + "name": "minecraft:candle", + "id": -412 + }, + { + "name": "minecraft:candle_cake", + "id": -429 + }, + { + "name": "minecraft:carpet", + "id": 727 + }, + { + "name": "minecraft:carrot", + "id": 284 + }, + { + "name": "minecraft:carrot_on_a_stick", + "id": 534 + }, + { + "name": "minecraft:carrots", + "id": 141 + }, + { + "name": "minecraft:cartography_table", + "id": -200 + }, + { + "name": "minecraft:carved_pumpkin", + "id": -155 + }, + { + "name": "minecraft:cat_spawn_egg", + "id": 499 + }, + { + "name": "minecraft:cauldron", + "id": 442 + }, + { + "name": "minecraft:cave_spider_spawn_egg", + "id": 467 + }, + { + "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": 639 + }, + { + "name": "minecraft:chain_command_block", + "id": 189 + }, + { + "name": "minecraft:chainmail_boots", + "id": 350 + }, + { + "name": "minecraft:chainmail_chestplate", + "id": 348 + }, + { + "name": "minecraft:chainmail_helmet", + "id": 347 + }, + { + "name": "minecraft:chainmail_leggings", + "id": 349 + }, + { + "name": "minecraft:charcoal", + "id": 310 + }, + { + "name": "minecraft:chemical_heat", + "id": 192 + }, + { + "name": "minecraft:chemistry_table", + "id": 238 + }, + { + "name": "minecraft:cherry_boat", + "id": 669 + }, + { + "name": "minecraft:cherry_button", + "id": -530 + }, + { + "name": "minecraft:cherry_chest_boat", + "id": 670 + }, + { + "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": 671 + }, + { + "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": 665 + }, + { + "name": "minecraft:chest_minecart", + "id": 398 + }, + { + "name": "minecraft:chicken", + "id": 280 + }, + { + "name": "minecraft:chicken_spawn_egg", + "id": 445 + }, + { + "name": "minecraft:chipped_anvil", + "id": -959 + }, + { + "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_quartz_block", + "id": -953 + }, + { + "name": "minecraft:chiseled_red_sandstone", + "id": -956 + }, + { + "name": "minecraft:chiseled_sandstone", + "id": -944 + }, + { + "name": "minecraft:chiseled_stone_bricks", + "id": -870 + }, + { + "name": "minecraft:chiseled_tuff", + "id": -753 + }, + { + "name": "minecraft:chiseled_tuff_bricks", + "id": -759 + }, + { + "name": "minecraft:chorus_flower", + "id": 200 + }, + { + "name": "minecraft:chorus_fruit", + "id": 575 + }, + { + "name": "minecraft:chorus_plant", + "id": 240 + }, + { + "name": "minecraft:clay", + "id": 82 + }, + { + "name": "minecraft:clay_ball", + "id": 393 + }, + { + "name": "minecraft:client_request_placeholder_block", + "id": -465 + }, + { + "name": "minecraft:clock", + "id": 402 + }, + { + "name": "minecraft:coal", + "id": 309 + }, + { + "name": "minecraft:coal_block", + "id": 173 + }, + { + "name": "minecraft:coal_ore", + "id": 16 + }, + { + "name": "minecraft:coarse_dirt", + "id": -962 + }, + { + "name": "minecraft:coast_armor_trim_smithing_template", + "id": 703 + }, + { + "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_double_slab", + "id": -879 + }, + { + "name": "minecraft:cobblestone_slab", + "id": -873 + }, + { + "name": "minecraft:cobblestone_wall", + "id": 139 + }, + { + "name": "minecraft:cocoa", + "id": 127 + }, + { + "name": "minecraft:cocoa_beans", + "id": 421 + }, + { + "name": "minecraft:cod", + "id": 269 + }, + { + "name": "minecraft:cod_bucket", + "id": 372 + }, + { + "name": "minecraft:cod_spawn_egg", + "id": 491 + }, + { + "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": 580 + }, + { + "name": "minecraft:comparator", + "id": 539 + }, + { + "name": "minecraft:compass", + "id": 400 + }, + { + "name": "minecraft:composter", + "id": -213 + }, + { + "name": "minecraft:compound", + "id": 614 + }, + { + "name": "minecraft:concrete", + "id": 753 + }, + { + "name": "minecraft:concrete_powder", + "id": 754 + }, + { + "name": "minecraft:conduit", + "id": -157 + }, + { + "name": "minecraft:cooked_beef", + "id": 279 + }, + { + "name": "minecraft:cooked_chicken", + "id": 281 + }, + { + "name": "minecraft:cooked_cod", + "id": 273 + }, + { + "name": "minecraft:cooked_mutton", + "id": 568 + }, + { + "name": "minecraft:cooked_porkchop", + "id": 268 + }, + { + "name": "minecraft:cooked_rabbit", + "id": 294 + }, + { + "name": "minecraft:cooked_salmon", + "id": 274 + }, + { + "name": "minecraft:cookie", + "id": 276 + }, + { + "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": 521 + }, + { + "name": "minecraft:copper_ore", + "id": -311 + }, + { + "name": "minecraft:copper_trapdoor", + "id": -792 + }, + { + "name": "minecraft:coral", + "id": 749 + }, + { + "name": "minecraft:coral_block", + "id": 731 + }, + { + "name": "minecraft:coral_fan", + "id": 740 + }, + { + "name": "minecraft:coral_fan_dead", + "id": 741 + }, + { + "name": "minecraft:cornflower", + "id": -838 + }, + { + "name": "minecraft:cow_spawn_egg", + "id": 446 + }, + { + "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:cracked_stone_bricks", + "id": -869 + }, + { + "name": "minecraft:crafter", + "id": -313 + }, + { + "name": "minecraft:crafting_table", + "id": 58 + }, + { + "name": "minecraft:creeper_banner_pattern", + "id": 599 + }, + { + "name": "minecraft:creeper_spawn_egg", + "id": 451 + }, + { + "name": "minecraft:crimson_button", + "id": -260 + }, + { + "name": "minecraft:crimson_door", + "id": 636 + }, + { + "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": 634 + }, + { + "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": 592 + }, + { + "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:cut_red_sandstone", + "id": -957 + }, + { + "name": "minecraft:cut_red_sandstone_double_slab", + "id": -928 + }, + { + "name": "minecraft:cut_red_sandstone_slab", + "id": -901 + }, + { + "name": "minecraft:cut_sandstone", + "id": -945 + }, + { + "name": "minecraft:cut_sandstone_double_slab", + "id": -927 + }, + { + "name": "minecraft:cut_sandstone_slab", + "id": -900 + }, + { + "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": 410 + }, + { + "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:damaged_anvil", + "id": -960 + }, + { + "name": "minecraft:dandelion", + "id": 37 + }, + { + "name": "minecraft:danger_pottery_sherd", + "id": 682 + }, + { + "name": "minecraft:dark_oak_boat", + "id": 389 + }, + { + "name": "minecraft:dark_oak_button", + "id": -142 + }, + { + "name": "minecraft:dark_oak_chest_boat", + "id": 663 + }, + { + "name": "minecraft:dark_oak_door", + "id": 574 + }, + { + "name": "minecraft:dark_oak_double_slab", + "id": -813 + }, + { + "name": "minecraft:dark_oak_fence", + "id": -577 + }, + { + "name": "minecraft:dark_oak_fence_gate", + "id": 186 + }, + { + "name": "minecraft:dark_oak_hanging_sign", + "id": -505 + }, + { + "name": "minecraft:dark_oak_leaves", + "id": -803 + }, + { + "name": "minecraft:dark_oak_log", + "id": -572 + }, + { + "name": "minecraft:dark_oak_planks", + "id": -743 + }, + { + "name": "minecraft:dark_oak_pressure_plate", + "id": -152 + }, + { + "name": "minecraft:dark_oak_sapling", + "id": -829 + }, + { + "name": "minecraft:dark_oak_sign", + "id": 597 + }, + { + "name": "minecraft:dark_oak_slab", + "id": -808 + }, + { + "name": "minecraft:dark_oak_stairs", + "id": 164 + }, + { + "name": "minecraft:dark_oak_trapdoor", + "id": -147 + }, + { + "name": "minecraft:dark_oak_wood", + "id": -818 + }, + { + "name": "minecraft:dark_prismarine", + "id": -947 + }, + { + "name": "minecraft:dark_prismarine_double_slab", + "id": -913 + }, + { + "name": "minecraft:dark_prismarine_slab", + "id": -886 + }, + { + "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_brain_coral_block", + "id": -854 + }, + { + "name": "minecraft:dead_brain_coral_fan", + "id": -844 + }, + { + "name": "minecraft:dead_brain_coral_wall_fan", + "id": -906 + }, + { + "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_bubble_coral_wall_fan", + "id": -908 + }, + { + "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_fire_coral_wall_fan", + "id": -909 + }, + { + "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_horn_coral_wall_fan", + "id": -910 + }, + { + "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:dead_tube_coral_wall_fan", + "id": -905 + }, + { + "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:deprecated_anvil", + "id": -961 + }, + { + "name": "minecraft:detector_rail", + "id": 28 + }, + { + "name": "minecraft:diamond", + "id": 311 + }, + { + "name": "minecraft:diamond_axe", + "id": 326 + }, + { + "name": "minecraft:diamond_block", + "id": 57 + }, + { + "name": "minecraft:diamond_boots", + "id": 358 + }, + { + "name": "minecraft:diamond_chestplate", + "id": 356 + }, + { + "name": "minecraft:diamond_helmet", + "id": 355 + }, + { + "name": "minecraft:diamond_hoe", + "id": 340 + }, + { + "name": "minecraft:diamond_horse_armor", + "id": 550 + }, + { + "name": "minecraft:diamond_leggings", + "id": 357 + }, + { + "name": "minecraft:diamond_ore", + "id": 56 + }, + { + "name": "minecraft:diamond_pickaxe", + "id": 325 + }, + { + "name": "minecraft:diamond_shovel", + "id": 324 + }, + { + "name": "minecraft:diamond_sword", + "id": 323 + }, + { + "name": "minecraft:diorite", + "id": -592 + }, + { + "name": "minecraft:diorite_double_slab", + "id": -921 + }, + { + "name": "minecraft:diorite_slab", + "id": -894 + }, + { + "name": "minecraft:diorite_stairs", + "id": -170 + }, + { + "name": "minecraft:dirt", + "id": 3 + }, + { + "name": "minecraft:dirt_with_roots", + "id": -318 + }, + { + "name": "minecraft:disc_fragment_5", + "id": 657 + }, + { + "name": "minecraft:dispenser", + "id": 23 + }, + { + "name": "minecraft:dolphin_spawn_egg", + "id": 495 + }, + { + "name": "minecraft:donkey_spawn_egg", + "id": 476 + }, + { + "name": "minecraft:double_cut_copper_slab", + "id": -368 + }, + { + "name": "minecraft:double_plant", + "id": 747 + }, + { + "name": "minecraft:double_stone_block_slab", + "id": 736 + }, + { + "name": "minecraft:double_stone_block_slab2", + "id": 737 + }, + { + "name": "minecraft:double_stone_block_slab3", + "id": 738 + }, + { + "name": "minecraft:double_stone_block_slab4", + "id": 739 + }, + { + "name": "minecraft:dragon_breath", + "id": 577 + }, + { + "name": "minecraft:dragon_egg", + "id": 122 + }, + { + "name": "minecraft:dried_kelp", + "id": 275 + }, + { + "name": "minecraft:dried_kelp_block", + "id": -139 + }, + { + "name": "minecraft:dripstone_block", + "id": -317 + }, + { + "name": "minecraft:dropper", + "id": 125 + }, + { + "name": "minecraft:drowned_spawn_egg", + "id": 494 + }, + { + "name": "minecraft:dune_armor_trim_smithing_template", + "id": 702 + }, + { + "name": "minecraft:dye", + "id": 766 + }, + { + "name": "minecraft:echo_shard", + "id": 667 + }, + { + "name": "minecraft:egg", + "id": 399 + }, + { + "name": "minecraft:elder_guardian_spawn_egg", + "id": 482 + }, + { + "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": 581 + }, + { + "name": "minecraft:emerald", + "id": 529 + }, + { + "name": "minecraft:emerald_block", + "id": 133 + }, + { + "name": "minecraft:emerald_ore", + "id": 129 + }, + { + "name": "minecraft:empty_map", + "id": 532 + }, + { + "name": "minecraft:enchanted_book", + "id": 538 + }, + { + "name": "minecraft:enchanted_golden_apple", + "id": 264 + }, + { + "name": "minecraft:enchanting_table", + "id": 116 + }, + { + "name": "minecraft:end_brick_stairs", + "id": -178 + }, + { + "name": "minecraft:end_bricks", + "id": 206 + }, + { + "name": "minecraft:end_crystal", + "id": 769 + }, + { + "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:end_stone_brick_double_slab", + "id": -167 + }, + { + "name": "minecraft:end_stone_brick_slab", + "id": -162 + }, + { + "name": "minecraft:ender_chest", + "id": 130 + }, + { + "name": "minecraft:ender_dragon_spawn_egg", + "id": 518 + }, + { + "name": "minecraft:ender_eye", + "id": 443 + }, + { + "name": "minecraft:ender_pearl", + "id": 431 + }, + { + "name": "minecraft:enderman_spawn_egg", + "id": 452 + }, + { + "name": "minecraft:endermite_spawn_egg", + "id": 470 + }, + { + "name": "minecraft:evoker_spawn_egg", + "id": 486 + }, + { + "name": "minecraft:experience_bottle", + "id": 525 + }, + { + "name": "minecraft:explorer_pottery_sherd", + "id": 683 + }, + { + "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": 706 + }, + { + "name": "minecraft:farmland", + "id": 60 + }, + { + "name": "minecraft:feather", + "id": 335 + }, + { + "name": "minecraft:fence", + "id": 729 + }, + { + "name": "minecraft:fence_gate", + "id": 107 + }, + { + "name": "minecraft:fermented_spider_eye", + "id": 438 + }, + { + "name": "minecraft:fern", + "id": -848 + }, + { + "name": "minecraft:field_masoned_banner_pattern", + "id": 602 + }, + { + "name": "minecraft:filled_map", + "id": 429 + }, + { + "name": "minecraft:fire", + "id": 51 + }, + { + "name": "minecraft:fire_charge", + "id": 526 + }, + { + "name": "minecraft:fire_coral", + "id": -583 + }, + { + "name": "minecraft:fire_coral_block", + "id": -851 + }, + { + "name": "minecraft:fire_coral_fan", + "id": -842 + }, + { + "name": "minecraft:fire_coral_wall_fan", + "id": -907 + }, + { + "name": "minecraft:firework_rocket", + "id": 536 + }, + { + "name": "minecraft:firework_star", + "id": 537 + }, + { + "name": "minecraft:fishing_rod", + "id": 401 + }, + { + "name": "minecraft:fletching_table", + "id": -201 + }, + { + "name": "minecraft:flint", + "id": 364 + }, + { + "name": "minecraft:flint_and_steel", + "id": 306 + }, + { + "name": "minecraft:flow_armor_trim_smithing_template", + "id": 717 + }, + { + "name": "minecraft:flow_banner_pattern", + "id": 606 + }, + { + "name": "minecraft:flow_pottery_sherd", + "id": 684 + }, + { + "name": "minecraft:flower_banner_pattern", + "id": 598 + }, + { + "name": "minecraft:flower_pot", + "id": 531 + }, + { + "name": "minecraft:flowering_azalea", + "id": -338 + }, + { + "name": "minecraft:flowing_lava", + "id": 10 + }, + { + "name": "minecraft:flowing_water", + "id": 8 + }, + { + "name": "minecraft:fox_spawn_egg", + "id": 501 + }, + { + "name": "minecraft:frame", + "id": 530 + }, + { + "name": "minecraft:friend_pottery_sherd", + "id": 685 + }, + { + "name": "minecraft:frog_spawn", + "id": -468 + }, + { + "name": "minecraft:frog_spawn_egg", + "id": 648 + }, + { + "name": "minecraft:frosted_ice", + "id": 207 + }, + { + "name": "minecraft:furnace", + "id": 61 + }, + { + "name": "minecraft:ghast_spawn_egg", + "id": 464 + }, + { + "name": "minecraft:ghast_tear", + "id": 434 + }, + { + "name": "minecraft:gilded_blackstone", + "id": -281 + }, + { + "name": "minecraft:glass", + "id": 20 + }, + { + "name": "minecraft:glass_bottle", + "id": 437 + }, + { + "name": "minecraft:glass_pane", + "id": 102 + }, + { + "name": "minecraft:glistering_melon_slice", + "id": 444 + }, + { + "name": "minecraft:globe_banner_pattern", + "id": 605 + }, + { + "name": "minecraft:glow_berries", + "id": 770 + }, + { + "name": "minecraft:glow_frame", + "id": 643 + }, + { + "name": "minecraft:glow_ink_sac", + "id": 520 + }, + { + "name": "minecraft:glow_lichen", + "id": -411 + }, + { + "name": "minecraft:glow_squid_spawn_egg", + "id": 515 + }, + { + "name": "minecraft:glow_stick", + "id": 621 + }, + { + "name": "minecraft:glowingobsidian", + "id": 246 + }, + { + "name": "minecraft:glowstone", + "id": 89 + }, + { + "name": "minecraft:glowstone_dust", + "id": 403 + }, + { + "name": "minecraft:goat_horn", + "id": 647 + }, + { + "name": "minecraft:goat_spawn_egg", + "id": 514 + }, + { + "name": "minecraft:gold_block", + "id": 41 + }, + { + "name": "minecraft:gold_ingot", + "id": 313 + }, + { + "name": "minecraft:gold_nugget", + "id": 435 + }, + { + "name": "minecraft:gold_ore", + "id": 14 + }, + { + "name": "minecraft:golden_apple", + "id": 263 + }, + { + "name": "minecraft:golden_axe", + "id": 333 + }, + { + "name": "minecraft:golden_boots", + "id": 362 + }, + { + "name": "minecraft:golden_carrot", + "id": 288 + }, + { + "name": "minecraft:golden_chestplate", + "id": 360 + }, + { + "name": "minecraft:golden_helmet", + "id": 359 + }, + { + "name": "minecraft:golden_hoe", + "id": 341 + }, + { + "name": "minecraft:golden_horse_armor", + "id": 549 + }, + { + "name": "minecraft:golden_leggings", + "id": 361 + }, + { + "name": "minecraft:golden_pickaxe", + "id": 332 + }, + { + "name": "minecraft:golden_rail", + "id": 27 + }, + { + "name": "minecraft:golden_shovel", + "id": 331 + }, + { + "name": "minecraft:golden_sword", + "id": 330 + }, + { + "name": "minecraft:granite", + "id": -590 + }, + { + "name": "minecraft:granite_double_slab", + "id": -923 + }, + { + "name": "minecraft:granite_slab", + "id": -896 + }, + { + "name": "minecraft:granite_stairs", + "id": -169 + }, + { + "name": "minecraft:grass_block", + "id": 2 + }, + { + "name": "minecraft:grass_path", + "id": 198 + }, + { + "name": "minecraft:gravel", + "id": 13 + }, + { + "name": "minecraft:gray_candle", + "id": -420 + }, + { + "name": "minecraft:gray_candle_cake", + "id": -437 + }, + { + "name": "minecraft:gray_carpet", + "id": -603 + }, + { + "name": "minecraft:gray_concrete", + "id": -634 + }, + { + "name": "minecraft:gray_concrete_powder", + "id": -715 + }, + { + "name": "minecraft:gray_dye", + "id": 412 + }, + { + "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": 406 + }, + { + "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": 471 + }, + { + "name": "minecraft:gunpowder", + "id": 336 + }, + { + "name": "minecraft:guster_banner_pattern", + "id": 607 + }, + { + "name": "minecraft:guster_pottery_sherd", + "id": 686 + }, + { + "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": 762 + }, + { + "name": "minecraft:hard_stained_glass_pane", + "id": 763 + }, + { + "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": 588 + }, + { + "name": "minecraft:heart_pottery_sherd", + "id": 687 + }, + { + "name": "minecraft:heartbreak_pottery_sherd", + "id": 688 + }, + { + "name": "minecraft:heavy_core", + "id": -316 + }, + { + "name": "minecraft:heavy_weighted_pressure_plate", + "id": 148 + }, + { + "name": "minecraft:hoglin_spawn_egg", + "id": 507 + }, + { + "name": "minecraft:honey_block", + "id": -220 + }, + { + "name": "minecraft:honey_bottle", + "id": 611 + }, + { + "name": "minecraft:honeycomb", + "id": 610 + }, + { + "name": "minecraft:honeycomb_block", + "id": -221 + }, + { + "name": "minecraft:hopper", + "id": 544 + }, + { + "name": "minecraft:hopper_minecart", + "id": 543 + }, + { + "name": "minecraft:horn_coral", + "id": -584 + }, + { + "name": "minecraft:horn_coral_block", + "id": -852 + }, + { + "name": "minecraft:horn_coral_fan", + "id": -843 + }, + { + "name": "minecraft:horn_coral_wall_fan", + "id": -137 + }, + { + "name": "minecraft:horse_spawn_egg", + "id": 468 + }, + { + "name": "minecraft:host_armor_trim_smithing_template", + "id": 716 + }, + { + "name": "minecraft:howl_pottery_sherd", + "id": 689 + }, + { + "name": "minecraft:husk_spawn_egg", + "id": 474 + }, + { + "name": "minecraft:ice", + "id": 79 + }, + { + "name": "minecraft:ice_bomb", + "id": 615 + }, + { + "name": "minecraft:infested_chiseled_stone_bricks", + "id": -862 + }, + { + "name": "minecraft:infested_cobblestone", + "id": -858 + }, + { + "name": "minecraft:infested_cracked_stone_bricks", + "id": -861 + }, + { + "name": "minecraft:infested_deepslate", + "id": -454 + }, + { + "name": "minecraft:infested_mossy_stone_bricks", + "id": -860 + }, + { + "name": "minecraft:infested_stone", + "id": 97 + }, + { + "name": "minecraft:infested_stone_bricks", + "id": -859 + }, + { + "name": "minecraft:info_update", + "id": 248 + }, + { + "name": "minecraft:info_update2", + "id": 249 + }, + { + "name": "minecraft:ink_sac", + "id": 422 + }, + { + "name": "minecraft:invisible_bedrock", + "id": 95 + }, + { + "name": "minecraft:iron_axe", + "id": 305 + }, + { + "name": "minecraft:iron_bars", + "id": 101 + }, + { + "name": "minecraft:iron_block", + "id": 42 + }, + { + "name": "minecraft:iron_boots", + "id": 354 + }, + { + "name": "minecraft:iron_chestplate", + "id": 352 + }, + { + "name": "minecraft:iron_door", + "id": 380 + }, + { + "name": "minecraft:iron_golem_spawn_egg", + "id": 516 + }, + { + "name": "minecraft:iron_helmet", + "id": 351 + }, + { + "name": "minecraft:iron_hoe", + "id": 339 + }, + { + "name": "minecraft:iron_horse_armor", + "id": 548 + }, + { + "name": "minecraft:iron_ingot", + "id": 312 + }, + { + "name": "minecraft:iron_leggings", + "id": 353 + }, + { + "name": "minecraft:iron_nugget", + "id": 586 + }, + { + "name": "minecraft:iron_ore", + "id": 15 + }, + { + "name": "minecraft:iron_pickaxe", + "id": 304 + }, + { + "name": "minecraft:iron_shovel", + "id": 303 + }, + { + "name": "minecraft:iron_sword", + "id": 314 + }, + { + "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": 386 + }, + { + "name": "minecraft:jungle_button", + "id": -143 + }, + { + "name": "minecraft:jungle_chest_boat", + "id": 660 + }, + { + "name": "minecraft:jungle_door", + "id": 572 + }, + { + "name": "minecraft:jungle_double_slab", + "id": -811 + }, + { + "name": "minecraft:jungle_fence", + "id": -578 + }, + { + "name": "minecraft:jungle_fence_gate", + "id": 185 + }, + { + "name": "minecraft:jungle_hanging_sign", + "id": -503 + }, + { + "name": "minecraft:jungle_leaves", + "id": -802 + }, + { + "name": "minecraft:jungle_log", + "id": -571 + }, + { + "name": "minecraft:jungle_planks", + "id": -741 + }, + { + "name": "minecraft:jungle_pressure_plate", + "id": -153 + }, + { + "name": "minecraft:jungle_sapling", + "id": -827 + }, + { + "name": "minecraft:jungle_sign", + "id": 595 + }, + { + "name": "minecraft:jungle_slab", + "id": -806 + }, + { + "name": "minecraft:jungle_stairs", + "id": 136 + }, + { + "name": "minecraft:jungle_standing_sign", + "id": -188 + }, + { + "name": "minecraft:jungle_trapdoor", + "id": -148 + }, + { + "name": "minecraft:jungle_wall_sign", + "id": -189 + }, + { + "name": "minecraft:jungle_wood", + "id": -816 + }, + { + "name": "minecraft:kelp", + "id": 391 + }, + { + "name": "minecraft:ladder", + "id": 65 + }, + { + "name": "minecraft:lantern", + "id": -208 + }, + { + "name": "minecraft:lapis_block", + "id": 22 + }, + { + "name": "minecraft:lapis_lazuli", + "id": 423 + }, + { + "name": "minecraft:lapis_ore", + "id": 21 + }, + { + "name": "minecraft:large_amethyst_bud", + "id": -330 + }, + { + "name": "minecraft:large_fern", + "id": -865 + }, + { + "name": "minecraft:lava", + "id": 11 + }, + { + "name": "minecraft:lava_bucket", + "id": 371 + }, + { + "name": "minecraft:lead", + "id": 564 + }, + { + "name": "minecraft:leather", + "id": 390 + }, + { + "name": "minecraft:leather_boots", + "id": 346 + }, + { + "name": "minecraft:leather_chestplate", + "id": 344 + }, + { + "name": "minecraft:leather_helmet", + "id": 343 + }, + { + "name": "minecraft:leather_horse_armor", + "id": 547 + }, + { + "name": "minecraft:leather_leggings", + "id": 345 + }, + { + "name": "minecraft:leaves", + "id": 743 + }, + { + "name": "minecraft:leaves2", + "id": 744 + }, + { + "name": "minecraft:lectern", + "id": -194 + }, + { + "name": "minecraft:lever", + "id": 69 + }, + { + "name": "minecraft:light_block", + "id": 764 + }, + { + "name": "minecraft:light_block_0", + "id": -215 + }, + { + "name": "minecraft:light_block_1", + "id": -929 + }, + { + "name": "minecraft:light_block_10", + "id": -938 + }, + { + "name": "minecraft:light_block_11", + "id": -939 + }, + { + "name": "minecraft:light_block_12", + "id": -940 + }, + { + "name": "minecraft:light_block_13", + "id": -941 + }, + { + "name": "minecraft:light_block_14", + "id": -942 + }, + { + "name": "minecraft:light_block_15", + "id": -943 + }, + { + "name": "minecraft:light_block_2", + "id": -930 + }, + { + "name": "minecraft:light_block_3", + "id": -931 + }, + { + "name": "minecraft:light_block_4", + "id": -932 + }, + { + "name": "minecraft:light_block_5", + "id": -933 + }, + { + "name": "minecraft:light_block_6", + "id": -934 + }, + { + "name": "minecraft:light_block_7", + "id": -935 + }, + { + "name": "minecraft:light_block_8", + "id": -936 + }, + { + "name": "minecraft:light_block_9", + "id": -937 + }, + { + "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": 416 + }, + { + "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": 411 + }, + { + "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:lilac", + "id": -863 + }, + { + "name": "minecraft:lily_of_the_valley", + "id": -839 + }, + { + "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": 414 + }, + { + "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": 579 + }, + { + "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": 484 + }, + { + "name": "minecraft:lodestone", + "id": -222 + }, + { + "name": "minecraft:lodestone_compass", + "id": 622 + }, + { + "name": "minecraft:log", + "id": 728 + }, + { + "name": "minecraft:log2", + "id": 751 + }, + { + "name": "minecraft:loom", + "id": -204 + }, + { + "name": "minecraft:mace", + "id": 327 + }, + { + "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": 417 + }, + { + "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": 440 + }, + { + "name": "minecraft:magma_cube_spawn_egg", + "id": 465 + }, + { + "name": "minecraft:mangrove_boat", + "id": 655 + }, + { + "name": "minecraft:mangrove_button", + "id": -487 + }, + { + "name": "minecraft:mangrove_chest_boat", + "id": 664 + }, + { + "name": "minecraft:mangrove_door", + "id": 653 + }, + { + "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": 654 + }, + { + "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": 619 + }, + { + "name": "minecraft:medium_amethyst_bud", + "id": -331 + }, + { + "name": "minecraft:melon_block", + "id": 103 + }, + { + "name": "minecraft:melon_seeds", + "id": 298 + }, + { + "name": "minecraft:melon_slice", + "id": 277 + }, + { + "name": "minecraft:melon_stem", + "id": 105 + }, + { + "name": "minecraft:milk_bucket", + "id": 369 + }, + { + "name": "minecraft:minecart", + "id": 378 + }, + { + "name": "minecraft:miner_pottery_sherd", + "id": 690 + }, + { + "name": "minecraft:mob_spawner", + "id": 52 + }, + { + "name": "minecraft:mojang_banner_pattern", + "id": 601 + }, + { + "name": "minecraft:monster_egg", + "id": 752 + }, + { + "name": "minecraft:mooshroom_spawn_egg", + "id": 450 + }, + { + "name": "minecraft:moss_block", + "id": -320 + }, + { + "name": "minecraft:moss_carpet", + "id": -335 + }, + { + "name": "minecraft:mossy_cobblestone", + "id": 48 + }, + { + "name": "minecraft:mossy_cobblestone_double_slab", + "id": -915 + }, + { + "name": "minecraft:mossy_cobblestone_slab", + "id": -888 + }, + { + "name": "minecraft:mossy_cobblestone_stairs", + "id": -179 + }, + { + "name": "minecraft:mossy_stone_brick_double_slab", + "id": -168 + }, + { + "name": "minecraft:mossy_stone_brick_slab", + "id": -166 + }, + { + "name": "minecraft:mossy_stone_brick_stairs", + "id": -175 + }, + { + "name": "minecraft:mossy_stone_bricks", + "id": -868 + }, + { + "name": "minecraft:mourner_pottery_sherd", + "id": 691 + }, + { + "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": 477 + }, + { + "name": "minecraft:mushroom_stew", + "id": 265 + }, + { + "name": "minecraft:music_disc_11", + "id": 561 + }, + { + "name": "minecraft:music_disc_13", + "id": 551 + }, + { + "name": "minecraft:music_disc_5", + "id": 656 + }, + { + "name": "minecraft:music_disc_blocks", + "id": 553 + }, + { + "name": "minecraft:music_disc_cat", + "id": 552 + }, + { + "name": "minecraft:music_disc_chirp", + "id": 554 + }, + { + "name": "minecraft:music_disc_creator", + "id": 759 + }, + { + "name": "minecraft:music_disc_creator_music_box", + "id": 760 + }, + { + "name": "minecraft:music_disc_far", + "id": 555 + }, + { + "name": "minecraft:music_disc_mall", + "id": 556 + }, + { + "name": "minecraft:music_disc_mellohi", + "id": 557 + }, + { + "name": "minecraft:music_disc_otherside", + "id": 646 + }, + { + "name": "minecraft:music_disc_pigstep", + "id": 640 + }, + { + "name": "minecraft:music_disc_precipice", + "id": 761 + }, + { + "name": "minecraft:music_disc_relic", + "id": 719 + }, + { + "name": "minecraft:music_disc_stal", + "id": 558 + }, + { + "name": "minecraft:music_disc_strad", + "id": 559 + }, + { + "name": "minecraft:music_disc_wait", + "id": 562 + }, + { + "name": "minecraft:music_disc_ward", + "id": 560 + }, + { + "name": "minecraft:mutton", + "id": 567 + }, + { + "name": "minecraft:mycelium", + "id": 110 + }, + { + "name": "minecraft:name_tag", + "id": 565 + }, + { + "name": "minecraft:nautilus_shell", + "id": 587 + }, + { + "name": "minecraft:nether_brick", + "id": 112 + }, + { + "name": "minecraft:nether_brick_double_slab", + "id": -883 + }, + { + "name": "minecraft:nether_brick_fence", + "id": 113 + }, + { + "name": "minecraft:nether_brick_slab", + "id": -877 + }, + { + "name": "minecraft:nether_brick_stairs", + "id": 114 + }, + { + "name": "minecraft:nether_gold_ore", + "id": -288 + }, + { + "name": "minecraft:nether_sprouts", + "id": 641 + }, + { + "name": "minecraft:nether_star", + "id": 535 + }, + { + "name": "minecraft:nether_wart", + "id": 299 + }, + { + "name": "minecraft:nether_wart_block", + "id": 214 + }, + { + "name": "minecraft:netherbrick", + "id": 540 + }, + { + "name": "minecraft:netherite_axe", + "id": 626 + }, + { + "name": "minecraft:netherite_block", + "id": -270 + }, + { + "name": "minecraft:netherite_boots", + "id": 632 + }, + { + "name": "minecraft:netherite_chestplate", + "id": 630 + }, + { + "name": "minecraft:netherite_helmet", + "id": 629 + }, + { + "name": "minecraft:netherite_hoe", + "id": 627 + }, + { + "name": "minecraft:netherite_ingot", + "id": 628 + }, + { + "name": "minecraft:netherite_leggings", + "id": 631 + }, + { + "name": "minecraft:netherite_pickaxe", + "id": 625 + }, + { + "name": "minecraft:netherite_scrap", + "id": 633 + }, + { + "name": "minecraft:netherite_shovel", + "id": 624 + }, + { + "name": "minecraft:netherite_sword", + "id": 623 + }, + { + "name": "minecraft:netherite_upgrade_smithing_template", + "id": 700 + }, + { + "name": "minecraft:netherrack", + "id": 87 + }, + { + "name": "minecraft:netherreactor", + "id": 247 + }, + { + "name": "minecraft:normal_stone_double_slab", + "id": -926 + }, + { + "name": "minecraft:normal_stone_slab", + "id": -899 + }, + { + "name": "minecraft:normal_stone_stairs", + "id": -180 + }, + { + "name": "minecraft:noteblock", + "id": 25 + }, + { + "name": "minecraft:npc_spawn_egg", + "id": 481 + }, + { + "name": "minecraft:oak_boat", + "id": 384 + }, + { + "name": "minecraft:oak_chest_boat", + "id": 658 + }, + { + "name": "minecraft:oak_double_slab", + "id": 157 + }, + { + "name": "minecraft:oak_fence", + "id": 85 + }, + { + "name": "minecraft:oak_hanging_sign", + "id": -500 + }, + { + "name": "minecraft:oak_leaves", + "id": 18 + }, + { + "name": "minecraft:oak_log", + "id": 17 + }, + { + "name": "minecraft:oak_planks", + "id": 5 + }, + { + "name": "minecraft:oak_sapling", + "id": 6 + }, + { + "name": "minecraft:oak_sign", + "id": 366 + }, + { + "name": "minecraft:oak_slab", + "id": 158 + }, + { + "name": "minecraft:oak_stairs", + "id": 53 + }, + { + "name": "minecraft:oak_wood", + "id": -212 + }, + { + "name": "minecraft:observer", + "id": 251 + }, + { + "name": "minecraft:obsidian", + "id": 49 + }, + { + "name": "minecraft:ocelot_spawn_egg", + "id": 461 + }, + { + "name": "minecraft:ochre_froglight", + "id": -471 + }, + { + "name": "minecraft:ominous_bottle", + "id": 612 + }, + { + "name": "minecraft:ominous_trial_key", + "id": 258 + }, + { + "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": 418 + }, + { + "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_tulip", + "id": -834 + }, + { + "name": "minecraft:orange_wool", + "id": -557 + }, + { + "name": "minecraft:oxeye_daisy", + "id": -837 + }, + { + "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": 365 + }, + { + "name": "minecraft:panda_spawn_egg", + "id": 500 + }, + { + "name": "minecraft:paper", + "id": 395 + }, + { + "name": "minecraft:parrot_spawn_egg", + "id": 489 + }, + { + "name": "minecraft:pearlescent_froglight", + "id": -469 + }, + { + "name": "minecraft:peony", + "id": -867 + }, + { + "name": "minecraft:petrified_oak_double_slab", + "id": -903 + }, + { + "name": "minecraft:petrified_oak_slab", + "id": -902 + }, + { + "name": "minecraft:phantom_membrane", + "id": 591 + }, + { + "name": "minecraft:phantom_spawn_egg", + "id": 497 + }, + { + "name": "minecraft:pig_spawn_egg", + "id": 447 + }, + { + "name": "minecraft:piglin_banner_pattern", + "id": 604 + }, + { + "name": "minecraft:piglin_brute_spawn_egg", + "id": 510 + }, + { + "name": "minecraft:piglin_spawn_egg", + "id": 508 + }, + { + "name": "minecraft:pillager_spawn_egg", + "id": 502 + }, + { + "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": 413 + }, + { + "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_tulip", + "id": -836 + }, + { + "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": 302 + }, + { + "name": "minecraft:planks", + "id": 748 + }, + { + "name": "minecraft:plenty_pottery_sherd", + "id": 692 + }, + { + "name": "minecraft:podzol", + "id": 243 + }, + { + "name": "minecraft:pointed_dripstone", + "id": -308 + }, + { + "name": "minecraft:poisonous_potato", + "id": 287 + }, + { + "name": "minecraft:polar_bear_spawn_egg", + "id": 483 + }, + { + "name": "minecraft:polished_andesite", + "id": -595 + }, + { + "name": "minecraft:polished_andesite_double_slab", + "id": -919 + }, + { + "name": "minecraft:polished_andesite_slab", + "id": -892 + }, + { + "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_double_slab", + "id": -922 + }, + { + "name": "minecraft:polished_diorite_slab", + "id": -895 + }, + { + "name": "minecraft:polished_diorite_stairs", + "id": -173 + }, + { + "name": "minecraft:polished_granite", + "id": -591 + }, + { + "name": "minecraft:polished_granite_double_slab", + "id": -924 + }, + { + "name": "minecraft:polished_granite_slab", + "id": -897 + }, + { + "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": 576 + }, + { + "name": "minecraft:poppy", + "id": 38 + }, + { + "name": "minecraft:porkchop", + "id": 267 + }, + { + "name": "minecraft:portal", + "id": 90 + }, + { + "name": "minecraft:potato", + "id": 285 + }, + { + "name": "minecraft:potatoes", + "id": 142 + }, + { + "name": "minecraft:potion", + "id": 436 + }, + { + "name": "minecraft:powder_snow", + "id": -306 + }, + { + "name": "minecraft:powder_snow_bucket", + "id": 376 + }, + { + "name": "minecraft:powered_comparator", + "id": 150 + }, + { + "name": "minecraft:powered_repeater", + "id": 94 + }, + { + "name": "minecraft:prismarine", + "id": 168 + }, + { + "name": "minecraft:prismarine_brick_double_slab", + "id": -914 + }, + { + "name": "minecraft:prismarine_brick_slab", + "id": -887 + }, + { + "name": "minecraft:prismarine_bricks", + "id": -948 + }, + { + "name": "minecraft:prismarine_bricks_stairs", + "id": -4 + }, + { + "name": "minecraft:prismarine_crystals", + "id": 566 + }, + { + "name": "minecraft:prismarine_double_slab", + "id": -912 + }, + { + "name": "minecraft:prismarine_shard", + "id": 582 + }, + { + "name": "minecraft:prismarine_slab", + "id": -885 + }, + { + "name": "minecraft:prismarine_stairs", + "id": -2 + }, + { + "name": "minecraft:prize_pottery_sherd", + "id": 693 + }, + { + "name": "minecraft:pufferfish", + "id": 272 + }, + { + "name": "minecraft:pufferfish_bucket", + "id": 375 + }, + { + "name": "minecraft:pufferfish_spawn_egg", + "id": 492 + }, + { + "name": "minecraft:pumpkin", + "id": 86 + }, + { + "name": "minecraft:pumpkin_pie", + "id": 289 + }, + { + "name": "minecraft:pumpkin_seeds", + "id": 297 + }, + { + "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": 409 + }, + { + "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_double_slab", + "id": -911 + }, + { + "name": "minecraft:purpur_slab", + "id": -884 + }, + { + "name": "minecraft:purpur_stairs", + "id": 203 + }, + { + "name": "minecraft:quartz", + "id": 541 + }, + { + "name": "minecraft:quartz_block", + "id": 155 + }, + { + "name": "minecraft:quartz_bricks", + "id": -304 + }, + { + "name": "minecraft:quartz_double_slab", + "id": -882 + }, + { + "name": "minecraft:quartz_ore", + "id": 153 + }, + { + "name": "minecraft:quartz_pillar", + "id": -954 + }, + { + "name": "minecraft:quartz_slab", + "id": -876 + }, + { + "name": "minecraft:quartz_stairs", + "id": 156 + }, + { + "name": "minecraft:rabbit", + "id": 293 + }, + { + "name": "minecraft:rabbit_foot", + "id": 545 + }, + { + "name": "minecraft:rabbit_hide", + "id": 546 + }, + { + "name": "minecraft:rabbit_spawn_egg", + "id": 469 + }, + { + "name": "minecraft:rabbit_stew", + "id": 295 + }, + { + "name": "minecraft:rail", + "id": 66 + }, + { + "name": "minecraft:raiser_armor_trim_smithing_template", + "id": 714 + }, + { + "name": "minecraft:rapid_fertilizer", + "id": 617 + }, + { + "name": "minecraft:ravager_spawn_egg", + "id": 504 + }, + { + "name": "minecraft:raw_copper", + "id": 524 + }, + { + "name": "minecraft:raw_copper_block", + "id": -452 + }, + { + "name": "minecraft:raw_gold", + "id": 523 + }, + { + "name": "minecraft:raw_gold_block", + "id": -453 + }, + { + "name": "minecraft:raw_iron", + "id": 522 + }, + { + "name": "minecraft:raw_iron_block", + "id": -451 + }, + { + "name": "minecraft:recovery_compass", + "id": 666 + }, + { + "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": 405 + }, + { + "name": "minecraft:red_flower", + "id": 746 + }, + { + "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_double_slab", + "id": -917 + }, + { + "name": "minecraft:red_nether_brick_slab", + "id": -890 + }, + { + "name": "minecraft:red_nether_brick_stairs", + "id": -184 + }, + { + "name": "minecraft:red_sand", + "id": -949 + }, + { + "name": "minecraft:red_sandstone", + "id": 179 + }, + { + "name": "minecraft:red_sandstone_double_slab", + "id": 181 + }, + { + "name": "minecraft:red_sandstone_slab", + "id": 182 + }, + { + "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_tulip", + "id": -833 + }, + { + "name": "minecraft:red_wool", + "id": -556 + }, + { + "name": "minecraft:redstone", + "id": 381 + }, + { + "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": 428 + }, + { + "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": 710 + }, + { + "name": "minecraft:rose_bush", + "id": -866 + }, + { + "name": "minecraft:rotten_flesh", + "id": 282 + }, + { + "name": "minecraft:saddle", + "id": 379 + }, + { + "name": "minecraft:salmon", + "id": 270 + }, + { + "name": "minecraft:salmon_bucket", + "id": 373 + }, + { + "name": "minecraft:salmon_spawn_egg", + "id": 493 + }, + { + "name": "minecraft:sand", + "id": 12 + }, + { + "name": "minecraft:sandstone", + "id": 24 + }, + { + "name": "minecraft:sandstone_double_slab", + "id": -878 + }, + { + "name": "minecraft:sandstone_slab", + "id": -872 + }, + { + "name": "minecraft:sandstone_stairs", + "id": 128 + }, + { + "name": "minecraft:sapling", + "id": 742 + }, + { + "name": "minecraft:scaffolding", + "id": -165 + }, + { + "name": "minecraft:scrape_pottery_sherd", + "id": 694 + }, + { + "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": 701 + }, + { + "name": "minecraft:shaper_armor_trim_smithing_template", + "id": 715 + }, + { + "name": "minecraft:sheaf_pottery_sherd", + "id": 695 + }, + { + "name": "minecraft:shears", + "id": 430 + }, + { + "name": "minecraft:sheep_spawn_egg", + "id": 448 + }, + { + "name": "minecraft:shelter_pottery_sherd", + "id": 696 + }, + { + "name": "minecraft:shield", + "id": 363 + }, + { + "name": "minecraft:short_grass", + "id": 31 + }, + { + "name": "minecraft:shroomlight", + "id": -230 + }, + { + "name": "minecraft:shulker_box", + "id": 757 + }, + { + "name": "minecraft:shulker_shell", + "id": 583 + }, + { + "name": "minecraft:shulker_spawn_egg", + "id": 480 + }, + { + "name": "minecraft:silence_armor_trim_smithing_template", + "id": 712 + }, + { + "name": "minecraft:silver_glazed_terracotta", + "id": 228 + }, + { + "name": "minecraft:silverfish_spawn_egg", + "id": 453 + }, + { + "name": "minecraft:skeleton_horse_spawn_egg", + "id": 478 + }, + { + "name": "minecraft:skeleton_spawn_egg", + "id": 454 + }, + { + "name": "minecraft:skull", + "id": 533 + }, + { + "name": "minecraft:skull_banner_pattern", + "id": 600 + }, + { + "name": "minecraft:skull_pottery_sherd", + "id": 697 + }, + { + "name": "minecraft:slime", + "id": 165 + }, + { + "name": "minecraft:slime_ball", + "id": 397 + }, + { + "name": "minecraft:slime_spawn_egg", + "id": 455 + }, + { + "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", + "id": -955 + }, + { + "name": "minecraft:smooth_quartz_double_slab", + "id": -925 + }, + { + "name": "minecraft:smooth_quartz_slab", + "id": -898 + }, + { + "name": "minecraft:smooth_quartz_stairs", + "id": -185 + }, + { + "name": "minecraft:smooth_red_sandstone", + "id": -958 + }, + { + "name": "minecraft:smooth_red_sandstone_double_slab", + "id": -918 + }, + { + "name": "minecraft:smooth_red_sandstone_slab", + "id": -891 + }, + { + "name": "minecraft:smooth_red_sandstone_stairs", + "id": -176 + }, + { + "name": "minecraft:smooth_sandstone", + "id": -946 + }, + { + "name": "minecraft:smooth_sandstone_double_slab", + "id": -916 + }, + { + "name": "minecraft:smooth_sandstone_slab", + "id": -889 + }, + { + "name": "minecraft:smooth_sandstone_stairs", + "id": -177 + }, + { + "name": "minecraft:smooth_stone", + "id": -183 + }, + { + "name": "minecraft:smooth_stone_double_slab", + "id": 43 + }, + { + "name": "minecraft:smooth_stone_slab", + "id": 44 + }, + { + "name": "minecraft:sniffer_egg", + "id": -596 + }, + { + "name": "minecraft:sniffer_spawn_egg", + "id": 511 + }, + { + "name": "minecraft:snort_pottery_sherd", + "id": 698 + }, + { + "name": "minecraft:snout_armor_trim_smithing_template", + "id": 709 + }, + { + "name": "minecraft:snow", + "id": 80 + }, + { + "name": "minecraft:snow_golem_spawn_egg", + "id": 517 + }, + { + "name": "minecraft:snow_layer", + "id": 78 + }, + { + "name": "minecraft:snowball", + "id": 382 + }, + { + "name": "minecraft:soul_campfire", + "id": 642 + }, + { + "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": 620 + }, + { + "name": "minecraft:spawn_egg", + "id": 768 + }, + { + "name": "minecraft:spider_eye", + "id": 283 + }, + { + "name": "minecraft:spider_spawn_egg", + "id": 456 + }, + { + "name": "minecraft:spire_armor_trim_smithing_template", + "id": 711 + }, + { + "name": "minecraft:splash_potion", + "id": 578 + }, + { + "name": "minecraft:sponge", + "id": 19 + }, + { + "name": "minecraft:spore_blossom", + "id": -321 + }, + { + "name": "minecraft:spruce_boat", + "id": 387 + }, + { + "name": "minecraft:spruce_button", + "id": -144 + }, + { + "name": "minecraft:spruce_chest_boat", + "id": 661 + }, + { + "name": "minecraft:spruce_door", + "id": 570 + }, + { + "name": "minecraft:spruce_double_slab", + "id": -809 + }, + { + "name": "minecraft:spruce_fence", + "id": -579 + }, + { + "name": "minecraft:spruce_fence_gate", + "id": 183 + }, + { + "name": "minecraft:spruce_hanging_sign", + "id": -501 + }, + { + "name": "minecraft:spruce_leaves", + "id": -800 + }, + { + "name": "minecraft:spruce_log", + "id": -569 + }, + { + "name": "minecraft:spruce_planks", + "id": -739 + }, + { + "name": "minecraft:spruce_pressure_plate", + "id": -154 + }, + { + "name": "minecraft:spruce_sapling", + "id": -825 + }, + { + "name": "minecraft:spruce_sign", + "id": 593 + }, + { + "name": "minecraft:spruce_slab", + "id": -804 + }, + { + "name": "minecraft:spruce_stairs", + "id": 134 + }, + { + "name": "minecraft:spruce_standing_sign", + "id": -181 + }, + { + "name": "minecraft:spruce_trapdoor", + "id": -149 + }, + { + "name": "minecraft:spruce_wall_sign", + "id": -182 + }, + { + "name": "minecraft:spruce_wood", + "id": -814 + }, + { + "name": "minecraft:spyglass", + "id": 645 + }, + { + "name": "minecraft:squid_spawn_egg", + "id": 460 + }, + { + "name": "minecraft:stained_glass", + "id": 755 + }, + { + "name": "minecraft:stained_glass_pane", + "id": 756 + }, + { + "name": "minecraft:stained_hardened_clay", + "id": 720 + }, + { + "name": "minecraft:standing_banner", + "id": 176 + }, + { + "name": "minecraft:standing_sign", + "id": 63 + }, + { + "name": "minecraft:stick", + "id": 328 + }, + { + "name": "minecraft:sticky_piston", + "id": 29 + }, + { + "name": "minecraft:sticky_piston_arm_collision", + "id": -217 + }, + { + "name": "minecraft:stone", + "id": 1 + }, + { + "name": "minecraft:stone_axe", + "id": 322 + }, + { + "name": "minecraft:stone_block_slab", + "id": 732 + }, + { + "name": "minecraft:stone_block_slab2", + "id": 733 + }, + { + "name": "minecraft:stone_block_slab3", + "id": 734 + }, + { + "name": "minecraft:stone_block_slab4", + "id": 735 + }, + { + "name": "minecraft:stone_brick_double_slab", + "id": -881 + }, + { + "name": "minecraft:stone_brick_slab", + "id": -875 + }, + { + "name": "minecraft:stone_brick_stairs", + "id": 109 + }, + { + "name": "minecraft:stone_bricks", + "id": 98 + }, + { + "name": "minecraft:stone_button", + "id": 77 + }, + { + "name": "minecraft:stone_hoe", + "id": 338 + }, + { + "name": "minecraft:stone_pickaxe", + "id": 321 + }, + { + "name": "minecraft:stone_pressure_plate", + "id": 70 + }, + { + "name": "minecraft:stone_shovel", + "id": 320 + }, + { + "name": "minecraft:stone_stairs", + "id": 67 + }, + { + "name": "minecraft:stone_sword", + "id": 319 + }, + { + "name": "minecraft:stonebrick", + "id": 730 + }, + { + "name": "minecraft:stonecutter", + "id": 245 + }, + { + "name": "minecraft:stonecutter_block", + "id": -197 + }, + { + "name": "minecraft:stray_spawn_egg", + "id": 472 + }, + { + "name": "minecraft:strider_spawn_egg", + "id": 506 + }, + { + "name": "minecraft:string", + "id": 334 + }, + { + "name": "minecraft:stripped_acacia_log", + "id": -8 + }, + { + "name": "minecraft:stripped_acacia_wood", + "id": -823 + }, + { + "name": "minecraft:stripped_bamboo_block", + "id": -528 + }, + { + "name": "minecraft:stripped_birch_log", + "id": -6 + }, + { + "name": "minecraft:stripped_birch_wood", + "id": -821 + }, + { + "name": "minecraft:stripped_cherry_log", + "id": -535 + }, + { + "name": "minecraft:stripped_cherry_wood", + "id": -545 + }, + { + "name": "minecraft:stripped_crimson_hyphae", + "id": -300 + }, + { + "name": "minecraft:stripped_crimson_stem", + "id": -240 + }, + { + "name": "minecraft:stripped_dark_oak_log", + "id": -9 + }, + { + "name": "minecraft:stripped_dark_oak_wood", + "id": -824 + }, + { + "name": "minecraft:stripped_jungle_log", + "id": -7 + }, + { + "name": "minecraft:stripped_jungle_wood", + "id": -822 + }, + { + "name": "minecraft:stripped_mangrove_log", + "id": -485 + }, + { + "name": "minecraft:stripped_mangrove_wood", + "id": -498 + }, + { + "name": "minecraft:stripped_oak_log", + "id": -10 + }, + { + "name": "minecraft:stripped_oak_wood", + "id": -819 + }, + { + "name": "minecraft:stripped_spruce_log", + "id": -5 + }, + { + "name": "minecraft:stripped_spruce_wood", + "id": -820 + }, + { + "name": "minecraft:stripped_warped_hyphae", + "id": -301 + }, + { + "name": "minecraft:stripped_warped_stem", + "id": -241 + }, + { + "name": "minecraft:structure_block", + "id": 252 + }, + { + "name": "minecraft:structure_void", + "id": 217 + }, + { + "name": "minecraft:sugar", + "id": 425 + }, + { + "name": "minecraft:sugar_cane", + "id": 394 + }, + { + "name": "minecraft:sunflower", + "id": 175 + }, + { + "name": "minecraft:suspicious_gravel", + "id": -573 + }, + { + "name": "minecraft:suspicious_sand", + "id": -529 + }, + { + "name": "minecraft:suspicious_stew", + "id": 609 + }, + { + "name": "minecraft:sweet_berries", + "id": 292 + }, + { + "name": "minecraft:sweet_berry_bush", + "id": -207 + }, + { + "name": "minecraft:tadpole_bucket", + "id": 650 + }, + { + "name": "minecraft:tadpole_spawn_egg", + "id": 649 + }, + { + "name": "minecraft:tall_grass", + "id": -864 + }, + { + "name": "minecraft:tallgrass", + "id": 750 + }, + { + "name": "minecraft:target", + "id": -239 + }, + { + "name": "minecraft:tide_armor_trim_smithing_template", + "id": 708 + }, + { + "name": "minecraft:tinted_glass", + "id": -334 + }, + { + "name": "minecraft:tnt", + "id": 46 + }, + { + "name": "minecraft:tnt_minecart", + "id": 542 + }, + { + "name": "minecraft:torch", + "id": 50 + }, + { + "name": "minecraft:torchflower", + "id": -568 + }, + { + "name": "minecraft:torchflower_crop", + "id": -567 + }, + { + "name": "minecraft:torchflower_seeds", + "id": 301 + }, + { + "name": "minecraft:totem_of_undying", + "id": 585 + }, + { + "name": "minecraft:trader_llama_spawn_egg", + "id": 668 + }, + { + "name": "minecraft:trapdoor", + "id": 96 + }, + { + "name": "minecraft:trapped_chest", + "id": 146 + }, + { + "name": "minecraft:trial_key", + "id": 259 + }, + { + "name": "minecraft:trial_spawner", + "id": -315 + }, + { + "name": "minecraft:trident", + "id": 563 + }, + { + "name": "minecraft:trip_wire", + "id": 132 + }, + { + "name": "minecraft:tripwire_hook", + "id": 131 + }, + { + "name": "minecraft:tropical_fish", + "id": 271 + }, + { + "name": "minecraft:tropical_fish_bucket", + "id": 374 + }, + { + "name": "minecraft:tropical_fish_spawn_egg", + "id": 490 + }, + { + "name": "minecraft:tube_coral", + "id": -131 + }, + { + "name": "minecraft:tube_coral_block", + "id": -132 + }, + { + "name": "minecraft:tube_coral_fan", + "id": -133 + }, + { + "name": "minecraft:tube_coral_wall_fan", + "id": -135 + }, + { + "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": 590 + }, + { + "name": "minecraft:turtle_scute", + "id": 589 + }, + { + "name": "minecraft:turtle_spawn_egg", + "id": 496 + }, + { + "name": "minecraft:twisting_vines", + "id": -287 + }, + { + "name": "minecraft:underwater_torch", + "id": 239 + }, + { + "name": "minecraft:undyed_shulker_box", + "id": 205 + }, + { + "name": "minecraft:unknown", + "id": -305 + }, + { + "name": "minecraft:unlit_redstone_torch", + "id": 75 + }, + { + "name": "minecraft:unpowered_comparator", + "id": 149 + }, + { + "name": "minecraft:unpowered_repeater", + "id": 93 + }, + { + "name": "minecraft:vault", + "id": -314 + }, + { + "name": "minecraft:verdant_froglight", + "id": -470 + }, + { + "name": "minecraft:vex_armor_trim_smithing_template", + "id": 707 + }, + { + "name": "minecraft:vex_spawn_egg", + "id": 487 + }, + { + "name": "minecraft:villager_spawn_egg", + "id": 459 + }, + { + "name": "minecraft:vindicator_spawn_egg", + "id": 485 + }, + { + "name": "minecraft:vine", + "id": 106 + }, + { + "name": "minecraft:wall_banner", + "id": 177 + }, + { + "name": "minecraft:wall_sign", + "id": 68 + }, + { + "name": "minecraft:wandering_trader_spawn_egg", + "id": 503 + }, + { + "name": "minecraft:ward_armor_trim_smithing_template", + "id": 705 + }, + { + "name": "minecraft:warden_spawn_egg", + "id": 652 + }, + { + "name": "minecraft:warped_button", + "id": -261 + }, + { + "name": "minecraft:warped_door", + "id": 637 + }, + { + "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": 638 + }, + { + "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": 635 + }, + { + "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": 370 + }, + { + "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": 713 + }, + { + "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": 342 + }, + { + "name": "minecraft:wheat_seeds", + "id": 296 + }, + { + "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": 419 + }, + { + "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_tulip", + "id": -835 + }, + { + "name": "minecraft:white_wool", + "id": 35 + }, + { + "name": "minecraft:wild_armor_trim_smithing_template", + "id": 704 + }, + { + "name": "minecraft:wind_charge", + "id": 260 + }, + { + "name": "minecraft:witch_spawn_egg", + "id": 462 + }, + { + "name": "minecraft:wither_rose", + "id": -216 + }, + { + "name": "minecraft:wither_skeleton_spawn_egg", + "id": 475 + }, + { + "name": "minecraft:wither_spawn_egg", + "id": 519 + }, + { + "name": "minecraft:wolf_armor", + "id": 723 + }, + { + "name": "minecraft:wolf_spawn_egg", + "id": 449 + }, + { + "name": "minecraft:wood", + "id": 758 + }, + { + "name": "minecraft:wooden_axe", + "id": 318 + }, + { + "name": "minecraft:wooden_button", + "id": 143 + }, + { + "name": "minecraft:wooden_door", + "id": 367 + }, + { + "name": "minecraft:wooden_hoe", + "id": 337 + }, + { + "name": "minecraft:wooden_pickaxe", + "id": 317 + }, + { + "name": "minecraft:wooden_pressure_plate", + "id": 72 + }, + { + "name": "minecraft:wooden_shovel", + "id": 316 + }, + { + "name": "minecraft:wooden_slab", + "id": 745 + }, + { + "name": "minecraft:wooden_sword", + "id": 315 + }, + { + "name": "minecraft:wool", + "id": 726 + }, + { + "name": "minecraft:writable_book", + "id": 527 + }, + { + "name": "minecraft:written_book", + "id": 528 + }, + { + "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": 415 + }, + { + "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": 509 + }, + { + "name": "minecraft:zombie_horse_spawn_egg", + "id": 479 + }, + { + "name": "minecraft:zombie_pigman_spawn_egg", + "id": 458 + }, + { + "name": "minecraft:zombie_spawn_egg", + "id": 457 + }, + { + "name": "minecraft:zombie_villager_spawn_egg", + "id": 488 + } +] \ No newline at end of file diff --git a/core/src/main/resources/bedrock/runtime_item_states.1_21_30.json b/core/src/main/resources/bedrock/runtime_item_states.1_21_30.json new file mode 100644 index 000000000..55bbe0a00 --- /dev/null +++ b/core/src/main/resources/bedrock/runtime_item_states.1_21_30.json @@ -0,0 +1,6898 @@ +[ + { + "name": "minecraft:acacia_boat", + "id": 388 + }, + { + "name": "minecraft:acacia_button", + "id": -140 + }, + { + "name": "minecraft:acacia_chest_boat", + "id": 662 + }, + { + "name": "minecraft:acacia_door", + "id": 573 + }, + { + "name": "minecraft:acacia_double_slab", + "id": -812 + }, + { + "name": "minecraft:acacia_fence", + "id": -575 + }, + { + "name": "minecraft:acacia_fence_gate", + "id": 187 + }, + { + "name": "minecraft:acacia_hanging_sign", + "id": -504 + }, + { + "name": "minecraft:acacia_leaves", + "id": 161 + }, + { + "name": "minecraft:acacia_log", + "id": 162 + }, + { + "name": "minecraft:acacia_planks", + "id": -742 + }, + { + "name": "minecraft:acacia_pressure_plate", + "id": -150 + }, + { + "name": "minecraft:acacia_sapling", + "id": -828 + }, + { + "name": "minecraft:acacia_sign", + "id": 596 + }, + { + "name": "minecraft:acacia_slab", + "id": -807 + }, + { + "name": "minecraft:acacia_stairs", + "id": 163 + }, + { + "name": "minecraft:acacia_standing_sign", + "id": -190 + }, + { + "name": "minecraft:acacia_trapdoor", + "id": -145 + }, + { + "name": "minecraft:acacia_wall_sign", + "id": -191 + }, + { + "name": "minecraft:acacia_wood", + "id": -817 + }, + { + "name": "minecraft:activator_rail", + "id": 126 + }, + { + "name": "minecraft:agent_spawn_egg", + "id": 498 + }, + { + "name": "minecraft:air", + "id": -158 + }, + { + "name": "minecraft:allay_spawn_egg", + "id": 651 + }, + { + "name": "minecraft:allium", + "id": -831 + }, + { + "name": "minecraft:allow", + "id": 210 + }, + { + "name": "minecraft:amethyst_block", + "id": -327 + }, + { + "name": "minecraft:amethyst_cluster", + "id": -329 + }, + { + "name": "minecraft:amethyst_shard", + "id": 644 + }, + { + "name": "minecraft:ancient_debris", + "id": -271 + }, + { + "name": "minecraft:andesite", + "id": -594 + }, + { + "name": "minecraft:andesite_double_slab", + "id": -920 + }, + { + "name": "minecraft:andesite_slab", + "id": -893 + }, + { + "name": "minecraft:andesite_stairs", + "id": -171 + }, + { + "name": "minecraft:andesite_wall", + "id": -974 + }, + { + "name": "minecraft:angler_pottery_sherd", + "id": 676 + }, + { + "name": "minecraft:anvil", + "id": 145 + }, + { + "name": "minecraft:apple", + "id": 261 + }, + { + "name": "minecraft:archer_pottery_sherd", + "id": 677 + }, + { + "name": "minecraft:armadillo_scute", + "id": 722 + }, + { + "name": "minecraft:armadillo_spawn_egg", + "id": 721 + }, + { + "name": "minecraft:armor_stand", + "id": 569 + }, + { + "name": "minecraft:arms_up_pottery_sherd", + "id": 678 + }, + { + "name": "minecraft:arrow", + "id": 308 + }, + { + "name": "minecraft:axolotl_bucket", + "id": 377 + }, + { + "name": "minecraft:axolotl_spawn_egg", + "id": 513 + }, + { + "name": "minecraft:azalea", + "id": -337 + }, + { + "name": "minecraft:azalea_leaves", + "id": -324 + }, + { + "name": "minecraft:azalea_leaves_flowered", + "id": -325 + }, + { + "name": "minecraft:azure_bluet", + "id": -832 + }, + { + "name": "minecraft:baked_potato", + "id": 286 + }, + { + "name": "minecraft:balloon", + "id": 618 + }, + { + "name": "minecraft:bamboo", + "id": -163 + }, + { + "name": "minecraft:bamboo_block", + "id": -527 + }, + { + "name": "minecraft:bamboo_button", + "id": -511 + }, + { + "name": "minecraft:bamboo_chest_raft", + "id": 674 + }, + { + "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": 673 + }, + { + "name": "minecraft:bamboo_sapling", + "id": -164 + }, + { + "name": "minecraft:bamboo_sign", + "id": 672 + }, + { + "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": 584 + }, + { + "name": "minecraft:banner_pattern", + "id": 770 + }, + { + "name": "minecraft:barrel", + "id": -203 + }, + { + "name": "minecraft:barrier", + "id": -161 + }, + { + "name": "minecraft:basalt", + "id": -234 + }, + { + "name": "minecraft:bat_spawn_egg", + "id": 463 + }, + { + "name": "minecraft:beacon", + "id": 138 + }, + { + "name": "minecraft:bed", + "id": 427 + }, + { + "name": "minecraft:bedrock", + "id": 7 + }, + { + "name": "minecraft:bee_nest", + "id": -218 + }, + { + "name": "minecraft:bee_spawn_egg", + "id": 505 + }, + { + "name": "minecraft:beef", + "id": 278 + }, + { + "name": "minecraft:beehive", + "id": -219 + }, + { + "name": "minecraft:beetroot", + "id": 290 + }, + { + "name": "minecraft:beetroot_seeds", + "id": 300 + }, + { + "name": "minecraft:beetroot_soup", + "id": 291 + }, + { + "name": "minecraft:bell", + "id": -206 + }, + { + "name": "minecraft:big_dripleaf", + "id": -323 + }, + { + "name": "minecraft:birch_boat", + "id": 385 + }, + { + "name": "minecraft:birch_button", + "id": -141 + }, + { + "name": "minecraft:birch_chest_boat", + "id": 659 + }, + { + "name": "minecraft:birch_door", + "id": 571 + }, + { + "name": "minecraft:birch_double_slab", + "id": -810 + }, + { + "name": "minecraft:birch_fence", + "id": -576 + }, + { + "name": "minecraft:birch_fence_gate", + "id": 184 + }, + { + "name": "minecraft:birch_hanging_sign", + "id": -502 + }, + { + "name": "minecraft:birch_leaves", + "id": -801 + }, + { + "name": "minecraft:birch_log", + "id": -570 + }, + { + "name": "minecraft:birch_planks", + "id": -740 + }, + { + "name": "minecraft:birch_pressure_plate", + "id": -151 + }, + { + "name": "minecraft:birch_sapling", + "id": -826 + }, + { + "name": "minecraft:birch_sign", + "id": 594 + }, + { + "name": "minecraft:birch_slab", + "id": -805 + }, + { + "name": "minecraft:birch_stairs", + "id": 135 + }, + { + "name": "minecraft:birch_standing_sign", + "id": -186 + }, + { + "name": "minecraft:birch_trapdoor", + "id": -146 + }, + { + "name": "minecraft:birch_wall_sign", + "id": -187 + }, + { + "name": "minecraft:birch_wood", + "id": -815 + }, + { + "name": "minecraft:black_candle", + "id": -428 + }, + { + "name": "minecraft:black_candle_cake", + "id": -445 + }, + { + "name": "minecraft:black_carpet", + "id": -611 + }, + { + "name": "minecraft:black_concrete", + "id": -642 + }, + { + "name": "minecraft:black_concrete_powder", + "id": -723 + }, + { + "name": "minecraft:black_dye", + "id": 404 + }, + { + "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": 679 + }, + { + "name": "minecraft:blast_furnace", + "id": -196 + }, + { + "name": "minecraft:blaze_powder", + "id": 439 + }, + { + "name": "minecraft:blaze_rod", + "id": 432 + }, + { + "name": "minecraft:blaze_spawn_egg", + "id": 466 + }, + { + "name": "minecraft:bleach", + "id": 616 + }, + { + "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": 408 + }, + { + "name": "minecraft:blue_glazed_terracotta", + "id": 231 + }, + { + "name": "minecraft:blue_ice", + "id": -11 + }, + { + "name": "minecraft:blue_orchid", + "id": -830 + }, + { + "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": 768 + }, + { + "name": "minecraft:bogged_spawn_egg", + "id": 473 + }, + { + "name": "minecraft:bolt_armor_trim_smithing_template", + "id": 718 + }, + { + "name": "minecraft:bone", + "id": 424 + }, + { + "name": "minecraft:bone_block", + "id": 216 + }, + { + "name": "minecraft:bone_meal", + "id": 420 + }, + { + "name": "minecraft:book", + "id": 396 + }, + { + "name": "minecraft:bookshelf", + "id": 47 + }, + { + "name": "minecraft:border_block", + "id": 212 + }, + { + "name": "minecraft:bordure_indented_banner_pattern", + "id": 603 + }, + { + "name": "minecraft:bow", + "id": 307 + }, + { + "name": "minecraft:bowl", + "id": 329 + }, + { + "name": "minecraft:brain_coral", + "id": -581 + }, + { + "name": "minecraft:brain_coral_block", + "id": -849 + }, + { + "name": "minecraft:brain_coral_fan", + "id": -840 + }, + { + "name": "minecraft:brain_coral_wall_fan", + "id": -904 + }, + { + "name": "minecraft:bread", + "id": 266 + }, + { + "name": "minecraft:breeze_rod", + "id": 257 + }, + { + "name": "minecraft:breeze_spawn_egg", + "id": 512 + }, + { + "name": "minecraft:brewer_pottery_sherd", + "id": 680 + }, + { + "name": "minecraft:brewing_stand", + "id": 441 + }, + { + "name": "minecraft:brick", + "id": 392 + }, + { + "name": "minecraft:brick_block", + "id": 45 + }, + { + "name": "minecraft:brick_double_slab", + "id": -880 + }, + { + "name": "minecraft:brick_slab", + "id": -874 + }, + { + "name": "minecraft:brick_stairs", + "id": 108 + }, + { + "name": "minecraft:brick_wall", + "id": -976 + }, + { + "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": 407 + }, + { + "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": 699 + }, + { + "name": "minecraft:bubble_column", + "id": -160 + }, + { + "name": "minecraft:bubble_coral", + "id": -582 + }, + { + "name": "minecraft:bubble_coral_block", + "id": -850 + }, + { + "name": "minecraft:bubble_coral_fan", + "id": -841 + }, + { + "name": "minecraft:bubble_coral_wall_fan", + "id": -136 + }, + { + "name": "minecraft:bucket", + "id": 368 + }, + { + "name": "minecraft:budding_amethyst", + "id": -328 + }, + { + "name": "minecraft:burn_pottery_sherd", + "id": 681 + }, + { + "name": "minecraft:cactus", + "id": 81 + }, + { + "name": "minecraft:cake", + "id": 426 + }, + { + "name": "minecraft:calcite", + "id": -326 + }, + { + "name": "minecraft:calibrated_sculk_sensor", + "id": -580 + }, + { + "name": "minecraft:camel_spawn_egg", + "id": 675 + }, + { + "name": "minecraft:camera", + "id": 613 + }, + { + "name": "minecraft:campfire", + "id": 608 + }, + { + "name": "minecraft:candle", + "id": -412 + }, + { + "name": "minecraft:candle_cake", + "id": -429 + }, + { + "name": "minecraft:carpet", + "id": 727 + }, + { + "name": "minecraft:carrot", + "id": 284 + }, + { + "name": "minecraft:carrot_on_a_stick", + "id": 534 + }, + { + "name": "minecraft:carrots", + "id": 141 + }, + { + "name": "minecraft:cartography_table", + "id": -200 + }, + { + "name": "minecraft:carved_pumpkin", + "id": -155 + }, + { + "name": "minecraft:cat_spawn_egg", + "id": 499 + }, + { + "name": "minecraft:cauldron", + "id": 442 + }, + { + "name": "minecraft:cave_spider_spawn_egg", + "id": 467 + }, + { + "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": 639 + }, + { + "name": "minecraft:chain_command_block", + "id": 189 + }, + { + "name": "minecraft:chainmail_boots", + "id": 350 + }, + { + "name": "minecraft:chainmail_chestplate", + "id": 348 + }, + { + "name": "minecraft:chainmail_helmet", + "id": 347 + }, + { + "name": "minecraft:chainmail_leggings", + "id": 349 + }, + { + "name": "minecraft:charcoal", + "id": 310 + }, + { + "name": "minecraft:chemical_heat", + "id": 192 + }, + { + "name": "minecraft:chemistry_table", + "id": 762 + }, + { + "name": "minecraft:cherry_boat", + "id": 669 + }, + { + "name": "minecraft:cherry_button", + "id": -530 + }, + { + "name": "minecraft:cherry_chest_boat", + "id": 670 + }, + { + "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": 671 + }, + { + "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": 665 + }, + { + "name": "minecraft:chest_minecart", + "id": 398 + }, + { + "name": "minecraft:chicken", + "id": 280 + }, + { + "name": "minecraft:chicken_spawn_egg", + "id": 445 + }, + { + "name": "minecraft:chipped_anvil", + "id": -959 + }, + { + "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_quartz_block", + "id": -953 + }, + { + "name": "minecraft:chiseled_red_sandstone", + "id": -956 + }, + { + "name": "minecraft:chiseled_sandstone", + "id": -944 + }, + { + "name": "minecraft:chiseled_stone_bricks", + "id": -870 + }, + { + "name": "minecraft:chiseled_tuff", + "id": -753 + }, + { + "name": "minecraft:chiseled_tuff_bricks", + "id": -759 + }, + { + "name": "minecraft:chorus_flower", + "id": 200 + }, + { + "name": "minecraft:chorus_fruit", + "id": 575 + }, + { + "name": "minecraft:chorus_plant", + "id": 240 + }, + { + "name": "minecraft:clay", + "id": 82 + }, + { + "name": "minecraft:clay_ball", + "id": 393 + }, + { + "name": "minecraft:client_request_placeholder_block", + "id": -465 + }, + { + "name": "minecraft:clock", + "id": 402 + }, + { + "name": "minecraft:coal", + "id": 309 + }, + { + "name": "minecraft:coal_block", + "id": 173 + }, + { + "name": "minecraft:coal_ore", + "id": 16 + }, + { + "name": "minecraft:coarse_dirt", + "id": -962 + }, + { + "name": "minecraft:coast_armor_trim_smithing_template", + "id": 703 + }, + { + "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_double_slab", + "id": -879 + }, + { + "name": "minecraft:cobblestone_slab", + "id": -873 + }, + { + "name": "minecraft:cobblestone_wall", + "id": 139 + }, + { + "name": "minecraft:cocoa", + "id": 127 + }, + { + "name": "minecraft:cocoa_beans", + "id": 421 + }, + { + "name": "minecraft:cod", + "id": 269 + }, + { + "name": "minecraft:cod_bucket", + "id": 372 + }, + { + "name": "minecraft:cod_spawn_egg", + "id": 491 + }, + { + "name": "minecraft:colored_torch_blue", + "id": 204 + }, + { + "name": "minecraft:colored_torch_bp", + "id": 766 + }, + { + "name": "minecraft:colored_torch_green", + "id": -963 + }, + { + "name": "minecraft:colored_torch_purple", + "id": -964 + }, + { + "name": "minecraft:colored_torch_red", + "id": 202 + }, + { + "name": "minecraft:colored_torch_rg", + "id": 765 + }, + { + "name": "minecraft:command_block", + "id": 137 + }, + { + "name": "minecraft:command_block_minecart", + "id": 580 + }, + { + "name": "minecraft:comparator", + "id": 539 + }, + { + "name": "minecraft:compass", + "id": 400 + }, + { + "name": "minecraft:composter", + "id": -213 + }, + { + "name": "minecraft:compound", + "id": 614 + }, + { + "name": "minecraft:compound_creator", + "id": 238 + }, + { + "name": "minecraft:concrete", + "id": 753 + }, + { + "name": "minecraft:concrete_powder", + "id": 754 + }, + { + "name": "minecraft:conduit", + "id": -157 + }, + { + "name": "minecraft:cooked_beef", + "id": 279 + }, + { + "name": "minecraft:cooked_chicken", + "id": 281 + }, + { + "name": "minecraft:cooked_cod", + "id": 273 + }, + { + "name": "minecraft:cooked_mutton", + "id": 568 + }, + { + "name": "minecraft:cooked_porkchop", + "id": 268 + }, + { + "name": "minecraft:cooked_rabbit", + "id": 294 + }, + { + "name": "minecraft:cooked_salmon", + "id": 274 + }, + { + "name": "minecraft:cookie", + "id": 276 + }, + { + "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": 521 + }, + { + "name": "minecraft:copper_ore", + "id": -311 + }, + { + "name": "minecraft:copper_trapdoor", + "id": -792 + }, + { + "name": "minecraft:coral", + "id": 749 + }, + { + "name": "minecraft:coral_block", + "id": 731 + }, + { + "name": "minecraft:coral_fan", + "id": 740 + }, + { + "name": "minecraft:coral_fan_dead", + "id": 741 + }, + { + "name": "minecraft:cornflower", + "id": -838 + }, + { + "name": "minecraft:cow_spawn_egg", + "id": 446 + }, + { + "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:cracked_stone_bricks", + "id": -869 + }, + { + "name": "minecraft:crafter", + "id": -313 + }, + { + "name": "minecraft:crafting_table", + "id": 58 + }, + { + "name": "minecraft:creeper_banner_pattern", + "id": 599 + }, + { + "name": "minecraft:creeper_spawn_egg", + "id": 451 + }, + { + "name": "minecraft:crimson_button", + "id": -260 + }, + { + "name": "minecraft:crimson_door", + "id": 636 + }, + { + "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": 634 + }, + { + "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": 592 + }, + { + "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:cut_red_sandstone", + "id": -957 + }, + { + "name": "minecraft:cut_red_sandstone_double_slab", + "id": -928 + }, + { + "name": "minecraft:cut_red_sandstone_slab", + "id": -901 + }, + { + "name": "minecraft:cut_sandstone", + "id": -945 + }, + { + "name": "minecraft:cut_sandstone_double_slab", + "id": -927 + }, + { + "name": "minecraft:cut_sandstone_slab", + "id": -900 + }, + { + "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": 410 + }, + { + "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:damaged_anvil", + "id": -960 + }, + { + "name": "minecraft:dandelion", + "id": 37 + }, + { + "name": "minecraft:danger_pottery_sherd", + "id": 682 + }, + { + "name": "minecraft:dark_oak_boat", + "id": 389 + }, + { + "name": "minecraft:dark_oak_button", + "id": -142 + }, + { + "name": "minecraft:dark_oak_chest_boat", + "id": 663 + }, + { + "name": "minecraft:dark_oak_door", + "id": 574 + }, + { + "name": "minecraft:dark_oak_double_slab", + "id": -813 + }, + { + "name": "minecraft:dark_oak_fence", + "id": -577 + }, + { + "name": "minecraft:dark_oak_fence_gate", + "id": 186 + }, + { + "name": "minecraft:dark_oak_hanging_sign", + "id": -505 + }, + { + "name": "minecraft:dark_oak_leaves", + "id": -803 + }, + { + "name": "minecraft:dark_oak_log", + "id": -572 + }, + { + "name": "minecraft:dark_oak_planks", + "id": -743 + }, + { + "name": "minecraft:dark_oak_pressure_plate", + "id": -152 + }, + { + "name": "minecraft:dark_oak_sapling", + "id": -829 + }, + { + "name": "minecraft:dark_oak_sign", + "id": 597 + }, + { + "name": "minecraft:dark_oak_slab", + "id": -808 + }, + { + "name": "minecraft:dark_oak_stairs", + "id": 164 + }, + { + "name": "minecraft:dark_oak_trapdoor", + "id": -147 + }, + { + "name": "minecraft:dark_oak_wood", + "id": -818 + }, + { + "name": "minecraft:dark_prismarine", + "id": -947 + }, + { + "name": "minecraft:dark_prismarine_double_slab", + "id": -913 + }, + { + "name": "minecraft:dark_prismarine_slab", + "id": -886 + }, + { + "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_brain_coral_block", + "id": -854 + }, + { + "name": "minecraft:dead_brain_coral_fan", + "id": -844 + }, + { + "name": "minecraft:dead_brain_coral_wall_fan", + "id": -906 + }, + { + "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_bubble_coral_wall_fan", + "id": -908 + }, + { + "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_fire_coral_wall_fan", + "id": -909 + }, + { + "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_horn_coral_wall_fan", + "id": -910 + }, + { + "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:dead_tube_coral_wall_fan", + "id": -905 + }, + { + "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:deprecated_anvil", + "id": -961 + }, + { + "name": "minecraft:deprecated_purpur_block_1", + "id": -950 + }, + { + "name": "minecraft:deprecated_purpur_block_2", + "id": -952 + }, + { + "name": "minecraft:detector_rail", + "id": 28 + }, + { + "name": "minecraft:diamond", + "id": 311 + }, + { + "name": "minecraft:diamond_axe", + "id": 326 + }, + { + "name": "minecraft:diamond_block", + "id": 57 + }, + { + "name": "minecraft:diamond_boots", + "id": 358 + }, + { + "name": "minecraft:diamond_chestplate", + "id": 356 + }, + { + "name": "minecraft:diamond_helmet", + "id": 355 + }, + { + "name": "minecraft:diamond_hoe", + "id": 340 + }, + { + "name": "minecraft:diamond_horse_armor", + "id": 550 + }, + { + "name": "minecraft:diamond_leggings", + "id": 357 + }, + { + "name": "minecraft:diamond_ore", + "id": 56 + }, + { + "name": "minecraft:diamond_pickaxe", + "id": 325 + }, + { + "name": "minecraft:diamond_shovel", + "id": 324 + }, + { + "name": "minecraft:diamond_sword", + "id": 323 + }, + { + "name": "minecraft:diorite", + "id": -592 + }, + { + "name": "minecraft:diorite_double_slab", + "id": -921 + }, + { + "name": "minecraft:diorite_slab", + "id": -894 + }, + { + "name": "minecraft:diorite_stairs", + "id": -170 + }, + { + "name": "minecraft:diorite_wall", + "id": -973 + }, + { + "name": "minecraft:dirt", + "id": 3 + }, + { + "name": "minecraft:dirt_with_roots", + "id": -318 + }, + { + "name": "minecraft:disc_fragment_5", + "id": 657 + }, + { + "name": "minecraft:dispenser", + "id": 23 + }, + { + "name": "minecraft:dolphin_spawn_egg", + "id": 495 + }, + { + "name": "minecraft:donkey_spawn_egg", + "id": 476 + }, + { + "name": "minecraft:double_cut_copper_slab", + "id": -368 + }, + { + "name": "minecraft:double_plant", + "id": 747 + }, + { + "name": "minecraft:double_stone_block_slab", + "id": 736 + }, + { + "name": "minecraft:double_stone_block_slab2", + "id": 737 + }, + { + "name": "minecraft:double_stone_block_slab3", + "id": 738 + }, + { + "name": "minecraft:double_stone_block_slab4", + "id": 739 + }, + { + "name": "minecraft:dragon_breath", + "id": 577 + }, + { + "name": "minecraft:dragon_egg", + "id": 122 + }, + { + "name": "minecraft:dried_kelp", + "id": 275 + }, + { + "name": "minecraft:dried_kelp_block", + "id": -139 + }, + { + "name": "minecraft:dripstone_block", + "id": -317 + }, + { + "name": "minecraft:dropper", + "id": 125 + }, + { + "name": "minecraft:drowned_spawn_egg", + "id": 494 + }, + { + "name": "minecraft:dune_armor_trim_smithing_template", + "id": 702 + }, + { + "name": "minecraft:dye", + "id": 769 + }, + { + "name": "minecraft:echo_shard", + "id": 667 + }, + { + "name": "minecraft:egg", + "id": 399 + }, + { + "name": "minecraft:elder_guardian_spawn_egg", + "id": 482 + }, + { + "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:element_constructor", + "id": -987 + }, + { + "name": "minecraft:elytra", + "id": 581 + }, + { + "name": "minecraft:emerald", + "id": 529 + }, + { + "name": "minecraft:emerald_block", + "id": 133 + }, + { + "name": "minecraft:emerald_ore", + "id": 129 + }, + { + "name": "minecraft:empty_map", + "id": 532 + }, + { + "name": "minecraft:enchanted_book", + "id": 538 + }, + { + "name": "minecraft:enchanted_golden_apple", + "id": 264 + }, + { + "name": "minecraft:enchanting_table", + "id": 116 + }, + { + "name": "minecraft:end_brick_stairs", + "id": -178 + }, + { + "name": "minecraft:end_bricks", + "id": 206 + }, + { + "name": "minecraft:end_crystal", + "id": 772 + }, + { + "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:end_stone_brick_double_slab", + "id": -167 + }, + { + "name": "minecraft:end_stone_brick_slab", + "id": -162 + }, + { + "name": "minecraft:end_stone_brick_wall", + "id": -980 + }, + { + "name": "minecraft:ender_chest", + "id": 130 + }, + { + "name": "minecraft:ender_dragon_spawn_egg", + "id": 518 + }, + { + "name": "minecraft:ender_eye", + "id": 443 + }, + { + "name": "minecraft:ender_pearl", + "id": 431 + }, + { + "name": "minecraft:enderman_spawn_egg", + "id": 452 + }, + { + "name": "minecraft:endermite_spawn_egg", + "id": 470 + }, + { + "name": "minecraft:evoker_spawn_egg", + "id": 486 + }, + { + "name": "minecraft:experience_bottle", + "id": 525 + }, + { + "name": "minecraft:explorer_pottery_sherd", + "id": 683 + }, + { + "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": 706 + }, + { + "name": "minecraft:farmland", + "id": 60 + }, + { + "name": "minecraft:feather", + "id": 335 + }, + { + "name": "minecraft:fence", + "id": 729 + }, + { + "name": "minecraft:fence_gate", + "id": 107 + }, + { + "name": "minecraft:fermented_spider_eye", + "id": 438 + }, + { + "name": "minecraft:fern", + "id": -848 + }, + { + "name": "minecraft:field_masoned_banner_pattern", + "id": 602 + }, + { + "name": "minecraft:filled_map", + "id": 429 + }, + { + "name": "minecraft:fire", + "id": 51 + }, + { + "name": "minecraft:fire_charge", + "id": 526 + }, + { + "name": "minecraft:fire_coral", + "id": -583 + }, + { + "name": "minecraft:fire_coral_block", + "id": -851 + }, + { + "name": "minecraft:fire_coral_fan", + "id": -842 + }, + { + "name": "minecraft:fire_coral_wall_fan", + "id": -907 + }, + { + "name": "minecraft:firework_rocket", + "id": 536 + }, + { + "name": "minecraft:firework_star", + "id": 537 + }, + { + "name": "minecraft:fishing_rod", + "id": 401 + }, + { + "name": "minecraft:fletching_table", + "id": -201 + }, + { + "name": "minecraft:flint", + "id": 364 + }, + { + "name": "minecraft:flint_and_steel", + "id": 306 + }, + { + "name": "minecraft:flow_armor_trim_smithing_template", + "id": 717 + }, + { + "name": "minecraft:flow_banner_pattern", + "id": 606 + }, + { + "name": "minecraft:flow_pottery_sherd", + "id": 684 + }, + { + "name": "minecraft:flower_banner_pattern", + "id": 598 + }, + { + "name": "minecraft:flower_pot", + "id": 531 + }, + { + "name": "minecraft:flowering_azalea", + "id": -338 + }, + { + "name": "minecraft:flowing_lava", + "id": 10 + }, + { + "name": "minecraft:flowing_water", + "id": 8 + }, + { + "name": "minecraft:fox_spawn_egg", + "id": 501 + }, + { + "name": "minecraft:frame", + "id": 530 + }, + { + "name": "minecraft:friend_pottery_sherd", + "id": 685 + }, + { + "name": "minecraft:frog_spawn", + "id": -468 + }, + { + "name": "minecraft:frog_spawn_egg", + "id": 648 + }, + { + "name": "minecraft:frosted_ice", + "id": 207 + }, + { + "name": "minecraft:furnace", + "id": 61 + }, + { + "name": "minecraft:ghast_spawn_egg", + "id": 464 + }, + { + "name": "minecraft:ghast_tear", + "id": 434 + }, + { + "name": "minecraft:gilded_blackstone", + "id": -281 + }, + { + "name": "minecraft:glass", + "id": 20 + }, + { + "name": "minecraft:glass_bottle", + "id": 437 + }, + { + "name": "minecraft:glass_pane", + "id": 102 + }, + { + "name": "minecraft:glistering_melon_slice", + "id": 444 + }, + { + "name": "minecraft:globe_banner_pattern", + "id": 605 + }, + { + "name": "minecraft:glow_berries", + "id": 773 + }, + { + "name": "minecraft:glow_frame", + "id": 643 + }, + { + "name": "minecraft:glow_ink_sac", + "id": 520 + }, + { + "name": "minecraft:glow_lichen", + "id": -411 + }, + { + "name": "minecraft:glow_squid_spawn_egg", + "id": 515 + }, + { + "name": "minecraft:glow_stick", + "id": 621 + }, + { + "name": "minecraft:glowingobsidian", + "id": 246 + }, + { + "name": "minecraft:glowstone", + "id": 89 + }, + { + "name": "minecraft:glowstone_dust", + "id": 403 + }, + { + "name": "minecraft:goat_horn", + "id": 647 + }, + { + "name": "minecraft:goat_spawn_egg", + "id": 514 + }, + { + "name": "minecraft:gold_block", + "id": 41 + }, + { + "name": "minecraft:gold_ingot", + "id": 313 + }, + { + "name": "minecraft:gold_nugget", + "id": 435 + }, + { + "name": "minecraft:gold_ore", + "id": 14 + }, + { + "name": "minecraft:golden_apple", + "id": 263 + }, + { + "name": "minecraft:golden_axe", + "id": 333 + }, + { + "name": "minecraft:golden_boots", + "id": 362 + }, + { + "name": "minecraft:golden_carrot", + "id": 288 + }, + { + "name": "minecraft:golden_chestplate", + "id": 360 + }, + { + "name": "minecraft:golden_helmet", + "id": 359 + }, + { + "name": "minecraft:golden_hoe", + "id": 341 + }, + { + "name": "minecraft:golden_horse_armor", + "id": 549 + }, + { + "name": "minecraft:golden_leggings", + "id": 361 + }, + { + "name": "minecraft:golden_pickaxe", + "id": 332 + }, + { + "name": "minecraft:golden_rail", + "id": 27 + }, + { + "name": "minecraft:golden_shovel", + "id": 331 + }, + { + "name": "minecraft:golden_sword", + "id": 330 + }, + { + "name": "minecraft:granite", + "id": -590 + }, + { + "name": "minecraft:granite_double_slab", + "id": -923 + }, + { + "name": "minecraft:granite_slab", + "id": -896 + }, + { + "name": "minecraft:granite_stairs", + "id": -169 + }, + { + "name": "minecraft:granite_wall", + "id": -972 + }, + { + "name": "minecraft:grass_block", + "id": 2 + }, + { + "name": "minecraft:grass_path", + "id": 198 + }, + { + "name": "minecraft:gravel", + "id": 13 + }, + { + "name": "minecraft:gray_candle", + "id": -420 + }, + { + "name": "minecraft:gray_candle_cake", + "id": -437 + }, + { + "name": "minecraft:gray_carpet", + "id": -603 + }, + { + "name": "minecraft:gray_concrete", + "id": -634 + }, + { + "name": "minecraft:gray_concrete_powder", + "id": -715 + }, + { + "name": "minecraft:gray_dye", + "id": 412 + }, + { + "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": 406 + }, + { + "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": 471 + }, + { + "name": "minecraft:gunpowder", + "id": 336 + }, + { + "name": "minecraft:guster_banner_pattern", + "id": 607 + }, + { + "name": "minecraft:guster_pottery_sherd", + "id": 686 + }, + { + "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": 763 + }, + { + "name": "minecraft:hard_stained_glass_pane", + "id": 764 + }, + { + "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": 588 + }, + { + "name": "minecraft:heart_pottery_sherd", + "id": 687 + }, + { + "name": "minecraft:heartbreak_pottery_sherd", + "id": 688 + }, + { + "name": "minecraft:heavy_core", + "id": -316 + }, + { + "name": "minecraft:heavy_weighted_pressure_plate", + "id": 148 + }, + { + "name": "minecraft:hoglin_spawn_egg", + "id": 507 + }, + { + "name": "minecraft:honey_block", + "id": -220 + }, + { + "name": "minecraft:honey_bottle", + "id": 611 + }, + { + "name": "minecraft:honeycomb", + "id": 610 + }, + { + "name": "minecraft:honeycomb_block", + "id": -221 + }, + { + "name": "minecraft:hopper", + "id": 544 + }, + { + "name": "minecraft:hopper_minecart", + "id": 543 + }, + { + "name": "minecraft:horn_coral", + "id": -584 + }, + { + "name": "minecraft:horn_coral_block", + "id": -852 + }, + { + "name": "minecraft:horn_coral_fan", + "id": -843 + }, + { + "name": "minecraft:horn_coral_wall_fan", + "id": -137 + }, + { + "name": "minecraft:horse_spawn_egg", + "id": 468 + }, + { + "name": "minecraft:host_armor_trim_smithing_template", + "id": 716 + }, + { + "name": "minecraft:howl_pottery_sherd", + "id": 689 + }, + { + "name": "minecraft:husk_spawn_egg", + "id": 474 + }, + { + "name": "minecraft:ice", + "id": 79 + }, + { + "name": "minecraft:ice_bomb", + "id": 615 + }, + { + "name": "minecraft:infested_chiseled_stone_bricks", + "id": -862 + }, + { + "name": "minecraft:infested_cobblestone", + "id": -858 + }, + { + "name": "minecraft:infested_cracked_stone_bricks", + "id": -861 + }, + { + "name": "minecraft:infested_deepslate", + "id": -454 + }, + { + "name": "minecraft:infested_mossy_stone_bricks", + "id": -860 + }, + { + "name": "minecraft:infested_stone", + "id": 97 + }, + { + "name": "minecraft:infested_stone_bricks", + "id": -859 + }, + { + "name": "minecraft:info_update", + "id": 248 + }, + { + "name": "minecraft:info_update2", + "id": 249 + }, + { + "name": "minecraft:ink_sac", + "id": 422 + }, + { + "name": "minecraft:invisible_bedrock", + "id": 95 + }, + { + "name": "minecraft:iron_axe", + "id": 305 + }, + { + "name": "minecraft:iron_bars", + "id": 101 + }, + { + "name": "minecraft:iron_block", + "id": 42 + }, + { + "name": "minecraft:iron_boots", + "id": 354 + }, + { + "name": "minecraft:iron_chestplate", + "id": 352 + }, + { + "name": "minecraft:iron_door", + "id": 380 + }, + { + "name": "minecraft:iron_golem_spawn_egg", + "id": 516 + }, + { + "name": "minecraft:iron_helmet", + "id": 351 + }, + { + "name": "minecraft:iron_hoe", + "id": 339 + }, + { + "name": "minecraft:iron_horse_armor", + "id": 548 + }, + { + "name": "minecraft:iron_ingot", + "id": 312 + }, + { + "name": "minecraft:iron_leggings", + "id": 353 + }, + { + "name": "minecraft:iron_nugget", + "id": 586 + }, + { + "name": "minecraft:iron_ore", + "id": 15 + }, + { + "name": "minecraft:iron_pickaxe", + "id": 304 + }, + { + "name": "minecraft:iron_shovel", + "id": 303 + }, + { + "name": "minecraft:iron_sword", + "id": 314 + }, + { + "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": 386 + }, + { + "name": "minecraft:jungle_button", + "id": -143 + }, + { + "name": "minecraft:jungle_chest_boat", + "id": 660 + }, + { + "name": "minecraft:jungle_door", + "id": 572 + }, + { + "name": "minecraft:jungle_double_slab", + "id": -811 + }, + { + "name": "minecraft:jungle_fence", + "id": -578 + }, + { + "name": "minecraft:jungle_fence_gate", + "id": 185 + }, + { + "name": "minecraft:jungle_hanging_sign", + "id": -503 + }, + { + "name": "minecraft:jungle_leaves", + "id": -802 + }, + { + "name": "minecraft:jungle_log", + "id": -571 + }, + { + "name": "minecraft:jungle_planks", + "id": -741 + }, + { + "name": "minecraft:jungle_pressure_plate", + "id": -153 + }, + { + "name": "minecraft:jungle_sapling", + "id": -827 + }, + { + "name": "minecraft:jungle_sign", + "id": 595 + }, + { + "name": "minecraft:jungle_slab", + "id": -806 + }, + { + "name": "minecraft:jungle_stairs", + "id": 136 + }, + { + "name": "minecraft:jungle_standing_sign", + "id": -188 + }, + { + "name": "minecraft:jungle_trapdoor", + "id": -148 + }, + { + "name": "minecraft:jungle_wall_sign", + "id": -189 + }, + { + "name": "minecraft:jungle_wood", + "id": -816 + }, + { + "name": "minecraft:kelp", + "id": 391 + }, + { + "name": "minecraft:lab_table", + "id": -988 + }, + { + "name": "minecraft:ladder", + "id": 65 + }, + { + "name": "minecraft:lantern", + "id": -208 + }, + { + "name": "minecraft:lapis_block", + "id": 22 + }, + { + "name": "minecraft:lapis_lazuli", + "id": 423 + }, + { + "name": "minecraft:lapis_ore", + "id": 21 + }, + { + "name": "minecraft:large_amethyst_bud", + "id": -330 + }, + { + "name": "minecraft:large_fern", + "id": -865 + }, + { + "name": "minecraft:lava", + "id": 11 + }, + { + "name": "minecraft:lava_bucket", + "id": 371 + }, + { + "name": "minecraft:lead", + "id": 564 + }, + { + "name": "minecraft:leather", + "id": 390 + }, + { + "name": "minecraft:leather_boots", + "id": 346 + }, + { + "name": "minecraft:leather_chestplate", + "id": 344 + }, + { + "name": "minecraft:leather_helmet", + "id": 343 + }, + { + "name": "minecraft:leather_horse_armor", + "id": 547 + }, + { + "name": "minecraft:leather_leggings", + "id": 345 + }, + { + "name": "minecraft:leaves", + "id": 743 + }, + { + "name": "minecraft:leaves2", + "id": 744 + }, + { + "name": "minecraft:lectern", + "id": -194 + }, + { + "name": "minecraft:lever", + "id": 69 + }, + { + "name": "minecraft:light_block", + "id": 767 + }, + { + "name": "minecraft:light_block_0", + "id": -215 + }, + { + "name": "minecraft:light_block_1", + "id": -929 + }, + { + "name": "minecraft:light_block_10", + "id": -938 + }, + { + "name": "minecraft:light_block_11", + "id": -939 + }, + { + "name": "minecraft:light_block_12", + "id": -940 + }, + { + "name": "minecraft:light_block_13", + "id": -941 + }, + { + "name": "minecraft:light_block_14", + "id": -942 + }, + { + "name": "minecraft:light_block_15", + "id": -943 + }, + { + "name": "minecraft:light_block_2", + "id": -930 + }, + { + "name": "minecraft:light_block_3", + "id": -931 + }, + { + "name": "minecraft:light_block_4", + "id": -932 + }, + { + "name": "minecraft:light_block_5", + "id": -933 + }, + { + "name": "minecraft:light_block_6", + "id": -934 + }, + { + "name": "minecraft:light_block_7", + "id": -935 + }, + { + "name": "minecraft:light_block_8", + "id": -936 + }, + { + "name": "minecraft:light_block_9", + "id": -937 + }, + { + "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": 416 + }, + { + "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": 411 + }, + { + "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:lilac", + "id": -863 + }, + { + "name": "minecraft:lily_of_the_valley", + "id": -839 + }, + { + "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": 414 + }, + { + "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": 579 + }, + { + "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": 484 + }, + { + "name": "minecraft:lodestone", + "id": -222 + }, + { + "name": "minecraft:lodestone_compass", + "id": 622 + }, + { + "name": "minecraft:log", + "id": 728 + }, + { + "name": "minecraft:log2", + "id": 751 + }, + { + "name": "minecraft:loom", + "id": -204 + }, + { + "name": "minecraft:mace", + "id": 327 + }, + { + "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": 417 + }, + { + "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": 440 + }, + { + "name": "minecraft:magma_cube_spawn_egg", + "id": 465 + }, + { + "name": "minecraft:mangrove_boat", + "id": 655 + }, + { + "name": "minecraft:mangrove_button", + "id": -487 + }, + { + "name": "minecraft:mangrove_chest_boat", + "id": 664 + }, + { + "name": "minecraft:mangrove_door", + "id": 653 + }, + { + "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": 654 + }, + { + "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:material_reducer", + "id": -986 + }, + { + "name": "minecraft:medicine", + "id": 619 + }, + { + "name": "minecraft:medium_amethyst_bud", + "id": -331 + }, + { + "name": "minecraft:melon_block", + "id": 103 + }, + { + "name": "minecraft:melon_seeds", + "id": 298 + }, + { + "name": "minecraft:melon_slice", + "id": 277 + }, + { + "name": "minecraft:melon_stem", + "id": 105 + }, + { + "name": "minecraft:milk_bucket", + "id": 369 + }, + { + "name": "minecraft:minecart", + "id": 378 + }, + { + "name": "minecraft:miner_pottery_sherd", + "id": 690 + }, + { + "name": "minecraft:mob_spawner", + "id": 52 + }, + { + "name": "minecraft:mojang_banner_pattern", + "id": 601 + }, + { + "name": "minecraft:monster_egg", + "id": 752 + }, + { + "name": "minecraft:mooshroom_spawn_egg", + "id": 450 + }, + { + "name": "minecraft:moss_block", + "id": -320 + }, + { + "name": "minecraft:moss_carpet", + "id": -335 + }, + { + "name": "minecraft:mossy_cobblestone", + "id": 48 + }, + { + "name": "minecraft:mossy_cobblestone_double_slab", + "id": -915 + }, + { + "name": "minecraft:mossy_cobblestone_slab", + "id": -888 + }, + { + "name": "minecraft:mossy_cobblestone_stairs", + "id": -179 + }, + { + "name": "minecraft:mossy_cobblestone_wall", + "id": -971 + }, + { + "name": "minecraft:mossy_stone_brick_double_slab", + "id": -168 + }, + { + "name": "minecraft:mossy_stone_brick_slab", + "id": -166 + }, + { + "name": "minecraft:mossy_stone_brick_stairs", + "id": -175 + }, + { + "name": "minecraft:mossy_stone_brick_wall", + "id": -978 + }, + { + "name": "minecraft:mossy_stone_bricks", + "id": -868 + }, + { + "name": "minecraft:mourner_pottery_sherd", + "id": 691 + }, + { + "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": 477 + }, + { + "name": "minecraft:mushroom_stew", + "id": 265 + }, + { + "name": "minecraft:music_disc_11", + "id": 561 + }, + { + "name": "minecraft:music_disc_13", + "id": 551 + }, + { + "name": "minecraft:music_disc_5", + "id": 656 + }, + { + "name": "minecraft:music_disc_blocks", + "id": 553 + }, + { + "name": "minecraft:music_disc_cat", + "id": 552 + }, + { + "name": "minecraft:music_disc_chirp", + "id": 554 + }, + { + "name": "minecraft:music_disc_creator", + "id": 759 + }, + { + "name": "minecraft:music_disc_creator_music_box", + "id": 760 + }, + { + "name": "minecraft:music_disc_far", + "id": 555 + }, + { + "name": "minecraft:music_disc_mall", + "id": 556 + }, + { + "name": "minecraft:music_disc_mellohi", + "id": 557 + }, + { + "name": "minecraft:music_disc_otherside", + "id": 646 + }, + { + "name": "minecraft:music_disc_pigstep", + "id": 640 + }, + { + "name": "minecraft:music_disc_precipice", + "id": 761 + }, + { + "name": "minecraft:music_disc_relic", + "id": 719 + }, + { + "name": "minecraft:music_disc_stal", + "id": 558 + }, + { + "name": "minecraft:music_disc_strad", + "id": 559 + }, + { + "name": "minecraft:music_disc_wait", + "id": 562 + }, + { + "name": "minecraft:music_disc_ward", + "id": 560 + }, + { + "name": "minecraft:mutton", + "id": 567 + }, + { + "name": "minecraft:mycelium", + "id": 110 + }, + { + "name": "minecraft:name_tag", + "id": 565 + }, + { + "name": "minecraft:nautilus_shell", + "id": 587 + }, + { + "name": "minecraft:nether_brick", + "id": 112 + }, + { + "name": "minecraft:nether_brick_double_slab", + "id": -883 + }, + { + "name": "minecraft:nether_brick_fence", + "id": 113 + }, + { + "name": "minecraft:nether_brick_slab", + "id": -877 + }, + { + "name": "minecraft:nether_brick_stairs", + "id": 114 + }, + { + "name": "minecraft:nether_brick_wall", + "id": -979 + }, + { + "name": "minecraft:nether_gold_ore", + "id": -288 + }, + { + "name": "minecraft:nether_sprouts", + "id": 641 + }, + { + "name": "minecraft:nether_star", + "id": 535 + }, + { + "name": "minecraft:nether_wart", + "id": 299 + }, + { + "name": "minecraft:nether_wart_block", + "id": 214 + }, + { + "name": "minecraft:netherbrick", + "id": 540 + }, + { + "name": "minecraft:netherite_axe", + "id": 626 + }, + { + "name": "minecraft:netherite_block", + "id": -270 + }, + { + "name": "minecraft:netherite_boots", + "id": 632 + }, + { + "name": "minecraft:netherite_chestplate", + "id": 630 + }, + { + "name": "minecraft:netherite_helmet", + "id": 629 + }, + { + "name": "minecraft:netherite_hoe", + "id": 627 + }, + { + "name": "minecraft:netherite_ingot", + "id": 628 + }, + { + "name": "minecraft:netherite_leggings", + "id": 631 + }, + { + "name": "minecraft:netherite_pickaxe", + "id": 625 + }, + { + "name": "minecraft:netherite_scrap", + "id": 633 + }, + { + "name": "minecraft:netherite_shovel", + "id": 624 + }, + { + "name": "minecraft:netherite_sword", + "id": 623 + }, + { + "name": "minecraft:netherite_upgrade_smithing_template", + "id": 700 + }, + { + "name": "minecraft:netherrack", + "id": 87 + }, + { + "name": "minecraft:netherreactor", + "id": 247 + }, + { + "name": "minecraft:normal_stone_double_slab", + "id": -926 + }, + { + "name": "minecraft:normal_stone_slab", + "id": -899 + }, + { + "name": "minecraft:normal_stone_stairs", + "id": -180 + }, + { + "name": "minecraft:noteblock", + "id": 25 + }, + { + "name": "minecraft:npc_spawn_egg", + "id": 481 + }, + { + "name": "minecraft:oak_boat", + "id": 384 + }, + { + "name": "minecraft:oak_chest_boat", + "id": 658 + }, + { + "name": "minecraft:oak_double_slab", + "id": 157 + }, + { + "name": "minecraft:oak_fence", + "id": 85 + }, + { + "name": "minecraft:oak_hanging_sign", + "id": -500 + }, + { + "name": "minecraft:oak_leaves", + "id": 18 + }, + { + "name": "minecraft:oak_log", + "id": 17 + }, + { + "name": "minecraft:oak_planks", + "id": 5 + }, + { + "name": "minecraft:oak_sapling", + "id": 6 + }, + { + "name": "minecraft:oak_sign", + "id": 366 + }, + { + "name": "minecraft:oak_slab", + "id": 158 + }, + { + "name": "minecraft:oak_stairs", + "id": 53 + }, + { + "name": "minecraft:oak_wood", + "id": -212 + }, + { + "name": "minecraft:observer", + "id": 251 + }, + { + "name": "minecraft:obsidian", + "id": 49 + }, + { + "name": "minecraft:ocelot_spawn_egg", + "id": 461 + }, + { + "name": "minecraft:ochre_froglight", + "id": -471 + }, + { + "name": "minecraft:ominous_bottle", + "id": 612 + }, + { + "name": "minecraft:ominous_trial_key", + "id": 258 + }, + { + "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": 418 + }, + { + "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_tulip", + "id": -834 + }, + { + "name": "minecraft:orange_wool", + "id": -557 + }, + { + "name": "minecraft:oxeye_daisy", + "id": -837 + }, + { + "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": 365 + }, + { + "name": "minecraft:panda_spawn_egg", + "id": 500 + }, + { + "name": "minecraft:paper", + "id": 395 + }, + { + "name": "minecraft:parrot_spawn_egg", + "id": 489 + }, + { + "name": "minecraft:pearlescent_froglight", + "id": -469 + }, + { + "name": "minecraft:peony", + "id": -867 + }, + { + "name": "minecraft:petrified_oak_double_slab", + "id": -903 + }, + { + "name": "minecraft:petrified_oak_slab", + "id": -902 + }, + { + "name": "minecraft:phantom_membrane", + "id": 591 + }, + { + "name": "minecraft:phantom_spawn_egg", + "id": 497 + }, + { + "name": "minecraft:pig_spawn_egg", + "id": 447 + }, + { + "name": "minecraft:piglin_banner_pattern", + "id": 604 + }, + { + "name": "minecraft:piglin_brute_spawn_egg", + "id": 510 + }, + { + "name": "minecraft:piglin_spawn_egg", + "id": 508 + }, + { + "name": "minecraft:pillager_spawn_egg", + "id": 502 + }, + { + "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": 413 + }, + { + "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_tulip", + "id": -836 + }, + { + "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": 302 + }, + { + "name": "minecraft:planks", + "id": 748 + }, + { + "name": "minecraft:plenty_pottery_sherd", + "id": 692 + }, + { + "name": "minecraft:podzol", + "id": 243 + }, + { + "name": "minecraft:pointed_dripstone", + "id": -308 + }, + { + "name": "minecraft:poisonous_potato", + "id": 287 + }, + { + "name": "minecraft:polar_bear_spawn_egg", + "id": 483 + }, + { + "name": "minecraft:polished_andesite", + "id": -595 + }, + { + "name": "minecraft:polished_andesite_double_slab", + "id": -919 + }, + { + "name": "minecraft:polished_andesite_slab", + "id": -892 + }, + { + "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_double_slab", + "id": -922 + }, + { + "name": "minecraft:polished_diorite_slab", + "id": -895 + }, + { + "name": "minecraft:polished_diorite_stairs", + "id": -173 + }, + { + "name": "minecraft:polished_granite", + "id": -591 + }, + { + "name": "minecraft:polished_granite_double_slab", + "id": -924 + }, + { + "name": "minecraft:polished_granite_slab", + "id": -897 + }, + { + "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": 576 + }, + { + "name": "minecraft:poppy", + "id": 38 + }, + { + "name": "minecraft:porkchop", + "id": 267 + }, + { + "name": "minecraft:portal", + "id": 90 + }, + { + "name": "minecraft:potato", + "id": 285 + }, + { + "name": "minecraft:potatoes", + "id": 142 + }, + { + "name": "minecraft:potion", + "id": 436 + }, + { + "name": "minecraft:powder_snow", + "id": -306 + }, + { + "name": "minecraft:powder_snow_bucket", + "id": 376 + }, + { + "name": "minecraft:powered_comparator", + "id": 150 + }, + { + "name": "minecraft:powered_repeater", + "id": 94 + }, + { + "name": "minecraft:prismarine", + "id": 168 + }, + { + "name": "minecraft:prismarine_brick_double_slab", + "id": -914 + }, + { + "name": "minecraft:prismarine_brick_slab", + "id": -887 + }, + { + "name": "minecraft:prismarine_bricks", + "id": -948 + }, + { + "name": "minecraft:prismarine_bricks_stairs", + "id": -4 + }, + { + "name": "minecraft:prismarine_crystals", + "id": 566 + }, + { + "name": "minecraft:prismarine_double_slab", + "id": -912 + }, + { + "name": "minecraft:prismarine_shard", + "id": 582 + }, + { + "name": "minecraft:prismarine_slab", + "id": -885 + }, + { + "name": "minecraft:prismarine_stairs", + "id": -2 + }, + { + "name": "minecraft:prismarine_wall", + "id": -981 + }, + { + "name": "minecraft:prize_pottery_sherd", + "id": 693 + }, + { + "name": "minecraft:pufferfish", + "id": 272 + }, + { + "name": "minecraft:pufferfish_bucket", + "id": 375 + }, + { + "name": "minecraft:pufferfish_spawn_egg", + "id": 492 + }, + { + "name": "minecraft:pumpkin", + "id": 86 + }, + { + "name": "minecraft:pumpkin_pie", + "id": 289 + }, + { + "name": "minecraft:pumpkin_seeds", + "id": 297 + }, + { + "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": 409 + }, + { + "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_double_slab", + "id": -911 + }, + { + "name": "minecraft:purpur_pillar", + "id": -951 + }, + { + "name": "minecraft:purpur_slab", + "id": -884 + }, + { + "name": "minecraft:purpur_stairs", + "id": 203 + }, + { + "name": "minecraft:quartz", + "id": 541 + }, + { + "name": "minecraft:quartz_block", + "id": 155 + }, + { + "name": "minecraft:quartz_bricks", + "id": -304 + }, + { + "name": "minecraft:quartz_double_slab", + "id": -882 + }, + { + "name": "minecraft:quartz_ore", + "id": 153 + }, + { + "name": "minecraft:quartz_pillar", + "id": -954 + }, + { + "name": "minecraft:quartz_slab", + "id": -876 + }, + { + "name": "minecraft:quartz_stairs", + "id": 156 + }, + { + "name": "minecraft:rabbit", + "id": 293 + }, + { + "name": "minecraft:rabbit_foot", + "id": 545 + }, + { + "name": "minecraft:rabbit_hide", + "id": 546 + }, + { + "name": "minecraft:rabbit_spawn_egg", + "id": 469 + }, + { + "name": "minecraft:rabbit_stew", + "id": 295 + }, + { + "name": "minecraft:rail", + "id": 66 + }, + { + "name": "minecraft:raiser_armor_trim_smithing_template", + "id": 714 + }, + { + "name": "minecraft:rapid_fertilizer", + "id": 617 + }, + { + "name": "minecraft:ravager_spawn_egg", + "id": 504 + }, + { + "name": "minecraft:raw_copper", + "id": 524 + }, + { + "name": "minecraft:raw_copper_block", + "id": -452 + }, + { + "name": "minecraft:raw_gold", + "id": 523 + }, + { + "name": "minecraft:raw_gold_block", + "id": -453 + }, + { + "name": "minecraft:raw_iron", + "id": 522 + }, + { + "name": "minecraft:raw_iron_block", + "id": -451 + }, + { + "name": "minecraft:recovery_compass", + "id": 666 + }, + { + "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": 405 + }, + { + "name": "minecraft:red_flower", + "id": 746 + }, + { + "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_double_slab", + "id": -917 + }, + { + "name": "minecraft:red_nether_brick_slab", + "id": -890 + }, + { + "name": "minecraft:red_nether_brick_stairs", + "id": -184 + }, + { + "name": "minecraft:red_nether_brick_wall", + "id": -983 + }, + { + "name": "minecraft:red_sand", + "id": -949 + }, + { + "name": "minecraft:red_sandstone", + "id": 179 + }, + { + "name": "minecraft:red_sandstone_double_slab", + "id": 181 + }, + { + "name": "minecraft:red_sandstone_slab", + "id": 182 + }, + { + "name": "minecraft:red_sandstone_stairs", + "id": 180 + }, + { + "name": "minecraft:red_sandstone_wall", + "id": -982 + }, + { + "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_tulip", + "id": -833 + }, + { + "name": "minecraft:red_wool", + "id": -556 + }, + { + "name": "minecraft:redstone", + "id": 381 + }, + { + "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": 428 + }, + { + "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": 710 + }, + { + "name": "minecraft:rose_bush", + "id": -866 + }, + { + "name": "minecraft:rotten_flesh", + "id": 282 + }, + { + "name": "minecraft:saddle", + "id": 379 + }, + { + "name": "minecraft:salmon", + "id": 270 + }, + { + "name": "minecraft:salmon_bucket", + "id": 373 + }, + { + "name": "minecraft:salmon_spawn_egg", + "id": 493 + }, + { + "name": "minecraft:sand", + "id": 12 + }, + { + "name": "minecraft:sandstone", + "id": 24 + }, + { + "name": "minecraft:sandstone_double_slab", + "id": -878 + }, + { + "name": "minecraft:sandstone_slab", + "id": -872 + }, + { + "name": "minecraft:sandstone_stairs", + "id": 128 + }, + { + "name": "minecraft:sandstone_wall", + "id": -975 + }, + { + "name": "minecraft:sapling", + "id": 742 + }, + { + "name": "minecraft:scaffolding", + "id": -165 + }, + { + "name": "minecraft:scrape_pottery_sherd", + "id": 694 + }, + { + "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": 701 + }, + { + "name": "minecraft:shaper_armor_trim_smithing_template", + "id": 715 + }, + { + "name": "minecraft:sheaf_pottery_sherd", + "id": 695 + }, + { + "name": "minecraft:shears", + "id": 430 + }, + { + "name": "minecraft:sheep_spawn_egg", + "id": 448 + }, + { + "name": "minecraft:shelter_pottery_sherd", + "id": 696 + }, + { + "name": "minecraft:shield", + "id": 363 + }, + { + "name": "minecraft:short_grass", + "id": 31 + }, + { + "name": "minecraft:shroomlight", + "id": -230 + }, + { + "name": "minecraft:shulker_box", + "id": 757 + }, + { + "name": "minecraft:shulker_shell", + "id": 583 + }, + { + "name": "minecraft:shulker_spawn_egg", + "id": 480 + }, + { + "name": "minecraft:silence_armor_trim_smithing_template", + "id": 712 + }, + { + "name": "minecraft:silver_glazed_terracotta", + "id": 228 + }, + { + "name": "minecraft:silverfish_spawn_egg", + "id": 453 + }, + { + "name": "minecraft:skeleton_horse_spawn_egg", + "id": 478 + }, + { + "name": "minecraft:skeleton_spawn_egg", + "id": 454 + }, + { + "name": "minecraft:skull", + "id": 533 + }, + { + "name": "minecraft:skull_banner_pattern", + "id": 600 + }, + { + "name": "minecraft:skull_pottery_sherd", + "id": 697 + }, + { + "name": "minecraft:slime", + "id": 165 + }, + { + "name": "minecraft:slime_ball", + "id": 397 + }, + { + "name": "minecraft:slime_spawn_egg", + "id": 455 + }, + { + "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", + "id": -955 + }, + { + "name": "minecraft:smooth_quartz_double_slab", + "id": -925 + }, + { + "name": "minecraft:smooth_quartz_slab", + "id": -898 + }, + { + "name": "minecraft:smooth_quartz_stairs", + "id": -185 + }, + { + "name": "minecraft:smooth_red_sandstone", + "id": -958 + }, + { + "name": "minecraft:smooth_red_sandstone_double_slab", + "id": -918 + }, + { + "name": "minecraft:smooth_red_sandstone_slab", + "id": -891 + }, + { + "name": "minecraft:smooth_red_sandstone_stairs", + "id": -176 + }, + { + "name": "minecraft:smooth_sandstone", + "id": -946 + }, + { + "name": "minecraft:smooth_sandstone_double_slab", + "id": -916 + }, + { + "name": "minecraft:smooth_sandstone_slab", + "id": -889 + }, + { + "name": "minecraft:smooth_sandstone_stairs", + "id": -177 + }, + { + "name": "minecraft:smooth_stone", + "id": -183 + }, + { + "name": "minecraft:smooth_stone_double_slab", + "id": 43 + }, + { + "name": "minecraft:smooth_stone_slab", + "id": 44 + }, + { + "name": "minecraft:sniffer_egg", + "id": -596 + }, + { + "name": "minecraft:sniffer_spawn_egg", + "id": 511 + }, + { + "name": "minecraft:snort_pottery_sherd", + "id": 698 + }, + { + "name": "minecraft:snout_armor_trim_smithing_template", + "id": 709 + }, + { + "name": "minecraft:snow", + "id": 80 + }, + { + "name": "minecraft:snow_golem_spawn_egg", + "id": 517 + }, + { + "name": "minecraft:snow_layer", + "id": 78 + }, + { + "name": "minecraft:snowball", + "id": 382 + }, + { + "name": "minecraft:soul_campfire", + "id": 642 + }, + { + "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": 620 + }, + { + "name": "minecraft:spawn_egg", + "id": 771 + }, + { + "name": "minecraft:spider_eye", + "id": 283 + }, + { + "name": "minecraft:spider_spawn_egg", + "id": 456 + }, + { + "name": "minecraft:spire_armor_trim_smithing_template", + "id": 711 + }, + { + "name": "minecraft:splash_potion", + "id": 578 + }, + { + "name": "minecraft:sponge", + "id": 19 + }, + { + "name": "minecraft:spore_blossom", + "id": -321 + }, + { + "name": "minecraft:spruce_boat", + "id": 387 + }, + { + "name": "minecraft:spruce_button", + "id": -144 + }, + { + "name": "minecraft:spruce_chest_boat", + "id": 661 + }, + { + "name": "minecraft:spruce_door", + "id": 570 + }, + { + "name": "minecraft:spruce_double_slab", + "id": -809 + }, + { + "name": "minecraft:spruce_fence", + "id": -579 + }, + { + "name": "minecraft:spruce_fence_gate", + "id": 183 + }, + { + "name": "minecraft:spruce_hanging_sign", + "id": -501 + }, + { + "name": "minecraft:spruce_leaves", + "id": -800 + }, + { + "name": "minecraft:spruce_log", + "id": -569 + }, + { + "name": "minecraft:spruce_planks", + "id": -739 + }, + { + "name": "minecraft:spruce_pressure_plate", + "id": -154 + }, + { + "name": "minecraft:spruce_sapling", + "id": -825 + }, + { + "name": "minecraft:spruce_sign", + "id": 593 + }, + { + "name": "minecraft:spruce_slab", + "id": -804 + }, + { + "name": "minecraft:spruce_stairs", + "id": 134 + }, + { + "name": "minecraft:spruce_standing_sign", + "id": -181 + }, + { + "name": "minecraft:spruce_trapdoor", + "id": -149 + }, + { + "name": "minecraft:spruce_wall_sign", + "id": -182 + }, + { + "name": "minecraft:spruce_wood", + "id": -814 + }, + { + "name": "minecraft:spyglass", + "id": 645 + }, + { + "name": "minecraft:squid_spawn_egg", + "id": 460 + }, + { + "name": "minecraft:stained_glass", + "id": 755 + }, + { + "name": "minecraft:stained_glass_pane", + "id": 756 + }, + { + "name": "minecraft:stained_hardened_clay", + "id": 720 + }, + { + "name": "minecraft:standing_banner", + "id": 176 + }, + { + "name": "minecraft:standing_sign", + "id": 63 + }, + { + "name": "minecraft:stick", + "id": 328 + }, + { + "name": "minecraft:sticky_piston", + "id": 29 + }, + { + "name": "minecraft:sticky_piston_arm_collision", + "id": -217 + }, + { + "name": "minecraft:stone", + "id": 1 + }, + { + "name": "minecraft:stone_axe", + "id": 322 + }, + { + "name": "minecraft:stone_block_slab", + "id": 732 + }, + { + "name": "minecraft:stone_block_slab2", + "id": 733 + }, + { + "name": "minecraft:stone_block_slab3", + "id": 734 + }, + { + "name": "minecraft:stone_block_slab4", + "id": 735 + }, + { + "name": "minecraft:stone_brick_double_slab", + "id": -881 + }, + { + "name": "minecraft:stone_brick_slab", + "id": -875 + }, + { + "name": "minecraft:stone_brick_stairs", + "id": 109 + }, + { + "name": "minecraft:stone_brick_wall", + "id": -977 + }, + { + "name": "minecraft:stone_bricks", + "id": 98 + }, + { + "name": "minecraft:stone_button", + "id": 77 + }, + { + "name": "minecraft:stone_hoe", + "id": 338 + }, + { + "name": "minecraft:stone_pickaxe", + "id": 321 + }, + { + "name": "minecraft:stone_pressure_plate", + "id": 70 + }, + { + "name": "minecraft:stone_shovel", + "id": 320 + }, + { + "name": "minecraft:stone_stairs", + "id": 67 + }, + { + "name": "minecraft:stone_sword", + "id": 319 + }, + { + "name": "minecraft:stonebrick", + "id": 730 + }, + { + "name": "minecraft:stonecutter", + "id": 245 + }, + { + "name": "minecraft:stonecutter_block", + "id": -197 + }, + { + "name": "minecraft:stray_spawn_egg", + "id": 472 + }, + { + "name": "minecraft:strider_spawn_egg", + "id": 506 + }, + { + "name": "minecraft:string", + "id": 334 + }, + { + "name": "minecraft:stripped_acacia_log", + "id": -8 + }, + { + "name": "minecraft:stripped_acacia_wood", + "id": -823 + }, + { + "name": "minecraft:stripped_bamboo_block", + "id": -528 + }, + { + "name": "minecraft:stripped_birch_log", + "id": -6 + }, + { + "name": "minecraft:stripped_birch_wood", + "id": -821 + }, + { + "name": "minecraft:stripped_cherry_log", + "id": -535 + }, + { + "name": "minecraft:stripped_cherry_wood", + "id": -545 + }, + { + "name": "minecraft:stripped_crimson_hyphae", + "id": -300 + }, + { + "name": "minecraft:stripped_crimson_stem", + "id": -240 + }, + { + "name": "minecraft:stripped_dark_oak_log", + "id": -9 + }, + { + "name": "minecraft:stripped_dark_oak_wood", + "id": -824 + }, + { + "name": "minecraft:stripped_jungle_log", + "id": -7 + }, + { + "name": "minecraft:stripped_jungle_wood", + "id": -822 + }, + { + "name": "minecraft:stripped_mangrove_log", + "id": -485 + }, + { + "name": "minecraft:stripped_mangrove_wood", + "id": -498 + }, + { + "name": "minecraft:stripped_oak_log", + "id": -10 + }, + { + "name": "minecraft:stripped_oak_wood", + "id": -819 + }, + { + "name": "minecraft:stripped_spruce_log", + "id": -5 + }, + { + "name": "minecraft:stripped_spruce_wood", + "id": -820 + }, + { + "name": "minecraft:stripped_warped_hyphae", + "id": -301 + }, + { + "name": "minecraft:stripped_warped_stem", + "id": -241 + }, + { + "name": "minecraft:structure_block", + "id": 252 + }, + { + "name": "minecraft:structure_void", + "id": 217 + }, + { + "name": "minecraft:sugar", + "id": 425 + }, + { + "name": "minecraft:sugar_cane", + "id": 394 + }, + { + "name": "minecraft:sunflower", + "id": 175 + }, + { + "name": "minecraft:suspicious_gravel", + "id": -573 + }, + { + "name": "minecraft:suspicious_sand", + "id": -529 + }, + { + "name": "minecraft:suspicious_stew", + "id": 609 + }, + { + "name": "minecraft:sweet_berries", + "id": 292 + }, + { + "name": "minecraft:sweet_berry_bush", + "id": -207 + }, + { + "name": "minecraft:tadpole_bucket", + "id": 650 + }, + { + "name": "minecraft:tadpole_spawn_egg", + "id": 649 + }, + { + "name": "minecraft:tall_grass", + "id": -864 + }, + { + "name": "minecraft:tallgrass", + "id": 750 + }, + { + "name": "minecraft:target", + "id": -239 + }, + { + "name": "minecraft:tide_armor_trim_smithing_template", + "id": 708 + }, + { + "name": "minecraft:tinted_glass", + "id": -334 + }, + { + "name": "minecraft:tnt", + "id": 46 + }, + { + "name": "minecraft:tnt_minecart", + "id": 542 + }, + { + "name": "minecraft:torch", + "id": 50 + }, + { + "name": "minecraft:torchflower", + "id": -568 + }, + { + "name": "minecraft:torchflower_crop", + "id": -567 + }, + { + "name": "minecraft:torchflower_seeds", + "id": 301 + }, + { + "name": "minecraft:totem_of_undying", + "id": 585 + }, + { + "name": "minecraft:trader_llama_spawn_egg", + "id": 668 + }, + { + "name": "minecraft:trapdoor", + "id": 96 + }, + { + "name": "minecraft:trapped_chest", + "id": 146 + }, + { + "name": "minecraft:trial_key", + "id": 259 + }, + { + "name": "minecraft:trial_spawner", + "id": -315 + }, + { + "name": "minecraft:trident", + "id": 563 + }, + { + "name": "minecraft:trip_wire", + "id": 132 + }, + { + "name": "minecraft:tripwire_hook", + "id": 131 + }, + { + "name": "minecraft:tropical_fish", + "id": 271 + }, + { + "name": "minecraft:tropical_fish_bucket", + "id": 374 + }, + { + "name": "minecraft:tropical_fish_spawn_egg", + "id": 490 + }, + { + "name": "minecraft:tube_coral", + "id": -131 + }, + { + "name": "minecraft:tube_coral_block", + "id": -132 + }, + { + "name": "minecraft:tube_coral_fan", + "id": -133 + }, + { + "name": "minecraft:tube_coral_wall_fan", + "id": -135 + }, + { + "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": 590 + }, + { + "name": "minecraft:turtle_scute", + "id": 589 + }, + { + "name": "minecraft:turtle_spawn_egg", + "id": 496 + }, + { + "name": "minecraft:twisting_vines", + "id": -287 + }, + { + "name": "minecraft:underwater_tnt", + "id": -985 + }, + { + "name": "minecraft:underwater_torch", + "id": 239 + }, + { + "name": "minecraft:undyed_shulker_box", + "id": 205 + }, + { + "name": "minecraft:unknown", + "id": -305 + }, + { + "name": "minecraft:unlit_redstone_torch", + "id": 75 + }, + { + "name": "minecraft:unpowered_comparator", + "id": 149 + }, + { + "name": "minecraft:unpowered_repeater", + "id": 93 + }, + { + "name": "minecraft:vault", + "id": -314 + }, + { + "name": "minecraft:verdant_froglight", + "id": -470 + }, + { + "name": "minecraft:vex_armor_trim_smithing_template", + "id": 707 + }, + { + "name": "minecraft:vex_spawn_egg", + "id": 487 + }, + { + "name": "minecraft:villager_spawn_egg", + "id": 459 + }, + { + "name": "minecraft:vindicator_spawn_egg", + "id": 485 + }, + { + "name": "minecraft:vine", + "id": 106 + }, + { + "name": "minecraft:wall_banner", + "id": 177 + }, + { + "name": "minecraft:wall_sign", + "id": 68 + }, + { + "name": "minecraft:wandering_trader_spawn_egg", + "id": 503 + }, + { + "name": "minecraft:ward_armor_trim_smithing_template", + "id": 705 + }, + { + "name": "minecraft:warden_spawn_egg", + "id": 652 + }, + { + "name": "minecraft:warped_button", + "id": -261 + }, + { + "name": "minecraft:warped_door", + "id": 637 + }, + { + "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": 638 + }, + { + "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": 635 + }, + { + "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": 370 + }, + { + "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": 713 + }, + { + "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:wet_sponge", + "id": -984 + }, + { + "name": "minecraft:wheat", + "id": 342 + }, + { + "name": "minecraft:wheat_seeds", + "id": 296 + }, + { + "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": 419 + }, + { + "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_tulip", + "id": -835 + }, + { + "name": "minecraft:white_wool", + "id": 35 + }, + { + "name": "minecraft:wild_armor_trim_smithing_template", + "id": 704 + }, + { + "name": "minecraft:wind_charge", + "id": 260 + }, + { + "name": "minecraft:witch_spawn_egg", + "id": 462 + }, + { + "name": "minecraft:wither_rose", + "id": -216 + }, + { + "name": "minecraft:wither_skeleton_spawn_egg", + "id": 475 + }, + { + "name": "minecraft:wither_spawn_egg", + "id": 519 + }, + { + "name": "minecraft:wolf_armor", + "id": 723 + }, + { + "name": "minecraft:wolf_spawn_egg", + "id": 449 + }, + { + "name": "minecraft:wood", + "id": 758 + }, + { + "name": "minecraft:wooden_axe", + "id": 318 + }, + { + "name": "minecraft:wooden_button", + "id": 143 + }, + { + "name": "minecraft:wooden_door", + "id": 367 + }, + { + "name": "minecraft:wooden_hoe", + "id": 337 + }, + { + "name": "minecraft:wooden_pickaxe", + "id": 317 + }, + { + "name": "minecraft:wooden_pressure_plate", + "id": 72 + }, + { + "name": "minecraft:wooden_shovel", + "id": 316 + }, + { + "name": "minecraft:wooden_slab", + "id": 745 + }, + { + "name": "minecraft:wooden_sword", + "id": 315 + }, + { + "name": "minecraft:wool", + "id": 726 + }, + { + "name": "minecraft:writable_book", + "id": 527 + }, + { + "name": "minecraft:written_book", + "id": 528 + }, + { + "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": 415 + }, + { + "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": 509 + }, + { + "name": "minecraft:zombie_horse_spawn_egg", + "id": 479 + }, + { + "name": "minecraft:zombie_pigman_spawn_egg", + "id": 458 + }, + { + "name": "minecraft:zombie_spawn_egg", + "id": 457 + }, + { + "name": "minecraft:zombie_villager_spawn_egg", + "id": 488 + } +] \ No newline at end of file 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) diff --git a/core/src/main/resources/languages b/core/src/main/resources/languages index afbf78bbe..7499daf71 160000 --- a/core/src/main/resources/languages +++ b/core/src/main/resources/languages @@ -1 +1 @@ -Subproject commit afbf78bbe0b39d0a076a42c228828c12f7f7da90 +Subproject commit 7499daf712ad6de70a07fba471b51b4ad92315c5 diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings index aaf53d695..93f207e7e 160000 --- a/core/src/main/resources/mappings +++ b/core/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit aaf53d6953c927e5ac1b87fd6627ffbfd4aa7cf5 +Subproject commit 93f207e7e9d73f58a7c8902f7deda9dcb0524c8e 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.properties b/gradle.properties index a222b1d99..1ee0e12cc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,11 +1,12 @@ # 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 group=org.geysermc id=geyser -version=2.4.0-SNAPSHOT +version=2.4.3-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 ae02a0079..f865bc2d8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] -base-api = "1.0.0-SNAPSHOT" +base-api = "1.0.1" cumulus = "1.1.2" -erosion = "1.1-20240515.191456-1" +erosion = "1.1-20240521.000109-3" events = "1.1-SNAPSHOT" jackson = "2.17.0" fastutil = "8.5.2" @@ -10,9 +10,11 @@ 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-20240704.153116-14" +protocol-connection = "3.0.0.Beta5-20240916.181041-6" +protocol-common = "3.0.0.Beta5-20240916.181041-6" +protocol-codec = "3.0.0.Beta5-20240916.181041-6" 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" @@ -24,17 +26,19 @@ 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" +viaproxy = "3.3.2-SNAPSHOT" fabric-loader = "0.15.11" fabric-api = "0.100.1+1.21" -fabric-permissions = "0.2-SNAPSHOT" -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" mockito = "5.+" # plugin versions @@ -87,8 +91,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" } @@ -98,7 +108,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" } @@ -119,15 +128,16 @@ 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" } mockito = { module = "org.mockito:mockito-core", version.ref = "mockito" } # 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" } @@ -135,7 +145,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" } 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()